home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 25 / AMIGAplus Sonderheft 25 (2000)(Falke)(DE)(Track 1 of 4)[!].iso / PublicDomain / Spiele / WormWars / Source / engine.c < prev    next >
C/C++ Source or Header  |  2000-04-26  |  151KB  |  4,162 lines

  1. /* $Filename: WormWars/Source/engine.c $
  2.  * $VER:      WormWars 5.61 $
  3.  *
  4.  * © Copyright 2000 James R. Jacobs.
  5.  */
  6.  
  7. #include <string.h>
  8. #include <math.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>            /* EXIT_SUCCESS, EXIT_FAILURE */
  11. #include <assert.h>
  12.  
  13. #include "stdafx.h"
  14. #include "diff.h"
  15. #include "same.h"
  16. #include "engine.h"
  17.  
  18. /* PRIVATE STRUCTURES -------------------------------------------------- */
  19.  
  20. struct
  21. {   SBYTE x, y, deltax, deltay;
  22.     ABOOL alive, moved, teleported, visible, reflected;
  23. } bullet[9];
  24. struct
  25. {   UWORD freq;
  26.     ULONG score;
  27. } object[LASTOBJECT + 1] =
  28. {   {1280,  60}, // AFFIXER
  29.     {  60,  20}, // AMMO
  30.     { 110,  20}, // ARMOUR
  31.     {  70,  50}, // BIAS
  32.     { 160,  30}, // BOMB
  33.     {  80,  10}, // BONUS
  34.     {1020,  60}, // CLOCK
  35.     { 250,  90}, // CYCLONE
  36.     { 330,  50}, // GROWER
  37.     {1900,  90}, // HEALER
  38.     {1360,  60}, // ICE
  39.     { 140,  60}, // LIFE
  40.     { 160,  80}, // LIGHTNING
  41.     { 970,  80}, // MAGNET
  42.     { 240,  40}, // MISSILE
  43.     { 640,  50}, // MULTIPLIER
  44.     { 400,  10}, // NITRO
  45.     { 240,  30}, // POWER
  46.     { 480,  50}, // PROTECTOR
  47.     { 210,  40}, // PULSE
  48.     { 400,  40}, // REMNANTS
  49.     { 500,  30}, // SIDESHOT
  50.     { 600,  40}, // SLAYER
  51.     { 980,  40}, // SLOWER
  52.     { 730,  70}, // SWITCHER
  53.     { 320,  20}, // TONGUE
  54.     {1500, 120}, // TREASURE
  55.     {3900, 140}  // UMBRELLA
  56. };
  57.  
  58. /*  -200    common
  59.     220-400 uncommon
  60.     420-980 rare
  61.     1000+   very rare */
  62.  
  63. struct
  64. {   SBYTE x, y, deltax, deltay, relx, rely;
  65.     ABOOL alive, last, visible;
  66. } protector[4][PROTECTORS + 1];
  67. struct
  68. {   SBYTE deltax, deltay;
  69. } thewormqueue[4][WORMQUEUELIMIT + 1];
  70. struct
  71. {   SBYTE deltax, deltay;
  72. } thedogqueue[CREATURES + 1][DOGQUEUELIMIT + 1];
  73. struct
  74. {   ABOOL alive;
  75.     SBYTE x, y, player;
  76.     UBYTE object;
  77. } magnet[MAGNETS + 1];
  78.  
  79. SBYTE eachworm[4][2][9] =
  80. {    {    {    GREENHEADUP,        GREENHEADUP,        GREENHEADUP,
  81.             GREENHEADLEFT,        ANYTHING,            GREENHEADRIGHT,
  82.             GREENHEADDOWN,        GREENHEADDOWN,        GREENHEADDOWN
  83.         },
  84.         {    GREENMODEUP,        GREENMODEUP,        GREENMODEUP,
  85.             GREENMODELEFT,        ANYTHING,            GREENMODERIGHT,
  86.             GREENMODEDOWN,        GREENMODEDOWN,        GREENMODEDOWN
  87.     }    },
  88.     {    {    REDHEADUP,        REDHEADUP,            REDHEADUP,
  89.             REDHEADLEFT,        ANYTHING,            REDHEADRIGHT,
  90.             REDHEADDOWN,        REDHEADDOWN,        REDHEADDOWN
  91.         },
  92.         {    REDMODEUP,        REDMODEUP,            REDMODEUP,
  93.             REDMODELEFT,        ANYTHING,            REDMODERIGHT,
  94.             REDMODEDOWN,        REDMODEDOWN,        REDMODEDOWN
  95.     }    },
  96.     {    {    BLUEHEADUP,        BLUEHEADUP,            BLUEHEADUP,
  97.             BLUEHEADLEFT,        ANYTHING,            BLUEHEADRIGHT,
  98.             BLUEHEADDOWN,        BLUEHEADDOWN,        BLUEHEADDOWN
  99.         },
  100.         {    BLUEMODEUP,        BLUEMODEUP,            BLUEMODEUP,
  101.             BLUEMODELEFT,        ANYTHING,            BLUEMODERIGHT,
  102.             BLUEMODEDOWN,        BLUEMODEDOWN,        BLUEMODEDOWN
  103.     }    },
  104.     {    {    YELLOWHEADUP,        YELLOWHEADUP,        YELLOWHEADUP,
  105.             YELLOWHEADLEFT,        ANYTHING,            YELLOWHEADRIGHT,
  106.             YELLOWHEADDOWN,        YELLOWHEADDOWN,        YELLOWHEADDOWN
  107.         },
  108.         {    YELLOWMODEUP,        YELLOWMODEUP,        YELLOWMODEUP,
  109.             YELLOWMODELEFT,        ANYTHING,            YELLOWMODERIGHT,
  110.             YELLOWMODEDOWN,        YELLOWMODEDOWN,        YELLOWMODEDOWN
  111. }    }    };
  112.  
  113. /* Rules for variable types:
  114.  
  115. SBYTE is used for field coordinates and queue indexes
  116. UBYTE is used for field contents
  117. SWORD is used for frequencies
  118. ULONG is used for scores */
  119.  
  120. struct
  121. {   ABOOL alive, explode, visible;
  122.     SBYTE x, y, deltax, deltay, pos, time;
  123.     UBYTE mode, dormant, multi, speed, last, oldlast, species,
  124.           type; // type is relevant worm 0-3 (for drips, missiles and dogs)
  125.     SWORD armour, tongue, freq;
  126.     ULONG score;
  127. } creature[CREATURES + 1];
  128.  
  129. // MODULE VARIABLES (used only within engine.c) ---------------------------
  130.  
  131. MODULE    ABOOL letters[4][LETTERS + 1], trainer;
  132. MODULE  SBYTE freq, ice, lettertype, letterx, lettery, leveltype,
  133.               treasurer;
  134.  
  135. // GLOBAL VARIABLES (owned by engine.c, imported by system.c) -------------
  136.  
  137. AGLOBAL    ABOOL clearthem = FALSE,
  138.               modified  = FALSE;
  139. AGLOBAL    SBYTE a         = GAMEOVER,
  140.               board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  141.               players,
  142.               field[FIELDX + 1][FIELDY + 1],
  143.               level = 1, levels, reallevel,
  144.               startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
  145. AGLOBAL    SWORD            secondsleft, secondsperlevel;
  146. AGLOBAL    TEXT            pathname[81],
  147.                                 date[DATELENGTH + 1],
  148.                                 times[TIMELENGTH + 1];
  149. AGLOBAL    ULONG            delay, r;
  150. AGLOBAL    struct HiScoreStruct    hiscore[HISCORES + 1];
  151. AGLOBAL    struct TeleportStruct    teleport[MAXLEVELS + 1][4];
  152. AGLOBAL    struct WormStruct       worm[4];
  153.  
  154. /* FUNCTIONS --------------------------------------------------------------
  155.  
  156. NAME        align -- right-justify a string within another string
  157. SYNOPSIS    align(STRPTR, SBYTE, TEXT);
  158. FUNCTION    Moves all text in a string to the right, padding with
  159.             spaces. Does not itself add a null terminator.
  160. INPUTS      string - pointer to the string of text
  161.               size - size in characters of the containing string
  162.             filler - what to pad the left of the string with
  163. NOTE        Null terminators are written over by this function, but that
  164.             does not matter, because calling functions use Text() with an
  165.             explicit length. This function only works with monospaced
  166.             fonts.
  167. MODULE      engine.c */
  168.  
  169. void align(STRPTR string, SBYTE size, TEXT filler)
  170. {   SBYTE i, shift, length;
  171.  
  172.     length = strlen((const char*) string);
  173.     shift = size - length;
  174.     for (i = 1; i <= length; i++)
  175.         *(string + size - i) = *(string + size - i - shift);
  176.     for (i = 0; i <= shift - 1; i++)
  177.         *(string + i) = filler;
  178. }
  179.  
  180. MODULE ABOOL blocked(SBYTE which, SBYTE deltax, SBYTE deltay)
  181. {   UBYTE c = field[xwrap(teleport[level][partner(which)].x + deltax)][ywrap(teleport[level][partner(which)].y + deltay)];
  182.     if ((c < STONE || c > GOAT) && c != METAL)
  183.         return FALSE;
  184.     else return TRUE;
  185. }
  186.  
  187. MODULE void bombblast(SBYTE triggerer, SBYTE player, SBYTE centrex, SBYTE centrey)
  188. {       SBYTE counter, downy, downymax, leftx, leftxmax, rightx, rightxmax, strength, uppy, uppymax, x, y;
  189.         ULONG score = 0;
  190.  
  191.     effect(FXBOMBBLAST);
  192.  
  193.     strength = BOMBADD + (rand() % BOMBRAND);
  194.  
  195.     leftxmax = centrex - strength;
  196.     if (leftxmax < 0)
  197.         leftxmax = 0;
  198.     rightxmax = centrex + strength;
  199.     if (rightxmax > FIELDX)
  200.         rightxmax = FIELDX;
  201.     uppymax = centrey - strength;
  202.     if (uppymax < 0)
  203.         uppymax = 0;
  204.     downymax = centrey + strength;
  205.     if (downymax > FIELDY)
  206.         downymax = FIELDY;
  207.  
  208.     leftx = centrex;
  209.     rightx = centrex;
  210.     uppy = centrey;
  211.     downy = centrey;
  212.     for (counter = 1; counter <= strength; counter++)
  213.     {    if (leftx > leftxmax)
  214.         {    leftx--;
  215.             for (y = uppy; y <= downy; y++)
  216.                 score += squareblast(triggerer, player, field[leftx][y], leftx, y);
  217.         }
  218.         if (rightx < rightxmax)
  219.         {    rightx++;
  220.             for (y = uppy; y <= downy; y++)
  221.                 score += squareblast(triggerer, player, field[rightx][y], rightx, y);
  222.         }
  223.         if (uppy > uppymax)
  224.         {    uppy--;
  225.             for (x = leftx; x <= rightx; x++)
  226.                 score += squareblast(triggerer, player, field[x][uppy], x, uppy);
  227.         }
  228.         if (downy < downymax)
  229.         {    downy++;
  230.             for (x = leftx; x <= rightx; x++)
  231.                 score += squareblast(triggerer, player, field[x][downy], x, downy);
  232.     }    }
  233.  
  234.     if (triggerer == HEAD)
  235.             wormscore(player, score);
  236.         elif (triggerer == ORB)
  237.             orbscore(player, score);
  238.         if (worm[player].bias)
  239.             stat(player, LIFE);
  240. }
  241.  
  242. MODULE void bouncegoat(SBYTE which, SBYTE x, SBYTE y)
  243. {   if (field[x][y] == GOAT)
  244.     {   creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  245.         orbscore(which, KILLGOAT);
  246.         change(x, y, BONUS);
  247. }   }
  248.  
  249. MODULE ABOOL bounceorb(SBYTE which, SBYTE x, SBYTE y)
  250. {    if (field[x][y] == METAL)
  251.         return TRUE;
  252.     elif (creature[which].mode == NONE)
  253.     {    if (field[x][y] >= FIRSTNONE && field[x][y] <= LASTNONE)
  254.             return TRUE;
  255.         else return FALSE;
  256.     } elif (creature[which].mode == TONGUE)
  257.     {    if (field[x][y] >= FIRSTTONGUE && field[x][y] <= LASTTONGUE)
  258.             return TRUE;
  259.         else return FALSE;
  260.     } else
  261.     {   /* assert(creature[which].mode == ARMOUR); */
  262.         if (field[x][y] >= FIRSTARMOUR && field[x][y] <= LASTARMOUR)
  263.             return TRUE;
  264.         else return FALSE;
  265. }   }
  266.  
  267. MODULE SBYTE bsign(SBYTE value)
  268. {   if (value < 0)
  269.         return (-1);
  270.     elif (value > 0)
  271.         return (1);
  272.     else return (0);
  273. }
  274.  
  275. MODULE void changefield(void)
  276. {   SBYTE x, y;
  277.  
  278.     for (x = 0; x <= FIELDX; x++)
  279.         for (y = 0; y <= FIELDY; y++)
  280.             field[x][y] = board[level][x][y];
  281. }
  282.  
  283. AGLOBAL void clearhiscores(void)
  284. {    SBYTE i;
  285.     
  286.     clearthem = FALSE;
  287.     for (i = 0; i <= HISCORES; i++)
  288.     {    hiscore[i].player = -1;
  289.         hiscore[i].level = 0;
  290.                 hiscore[i].score = 0;
  291.         hiscore[i].fresh = FALSE;
  292.         hiscore[i].name[0] = 0;
  293.         hiscore[i].time[0] = 0;
  294.         hiscore[i].date[0] = 0;
  295. }   }
  296.  
  297. MODULE void clearletters(void)
  298. {    SBYTE player, which;
  299.  
  300.     for (player = 0; player <= 3; player++)
  301.         for (which = 0; which <= LETTERS; which++)
  302.         {    letters[player][which] = FALSE;
  303.             drawletter(player, FIRSTLETTER + which, BLACK);
  304. }        }
  305.  
  306. MODULE void copyfield(SBYTE source, SBYTE destination)
  307. {    SBYTE which, x, y;
  308.  
  309.     for (x = 0; x <= FIELDX; x++)
  310.         for (y = 0; y <= FIELDY; y++)
  311.             board[destination][x][y] = board[source][x][y];
  312.     startx[destination] = startx[source];
  313.     starty[destination] = starty[source];
  314.     for (which = 0; which <= 1; which++)
  315.     {    teleport[destination][which].alive = teleport[source][which].alive;
  316.         teleport[destination][which].x     = teleport[source][which].x;
  317.         teleport[destination][which].y     = teleport[source][which].y;
  318. }    }
  319.  
  320. MODULE void death(void)
  321. {   SBYTE pain, player, which;
  322.     ABOOL slow;
  323.  
  324.     for (player = 0; player <= 3; player++)
  325.     {   if (worm[player].lives)
  326.         {   if (!worm[player].alive)
  327.             {   slow = FALSE;
  328.                 pain = 0;
  329.                 if (worm[player].cause >= FIRSTTAIL && worm[player].cause <= LASTTAIL)
  330.                 {   if (player == worm[player].cause - FIRSTTAIL)
  331.                         pain = TAILPAIN;
  332.                     else pain = OTHERTAILPAIN;
  333.                     slow = TRUE;
  334.                 } elif (worm[player].cause >= FIRSTFIRE && worm[player].cause <= LASTFIRE)
  335.                     pain = WORMFIREPAIN;
  336.                 elif (worm[player].cause >= FIRSTHEAD && worm[player].cause <= LASTHEAD)
  337.                     pain = HEADPAIN;
  338.                 elif (worm[player].cause >= FIRSTPROTECTOR && worm[player].cause <= LASTPROTECTOR)
  339.                     pain = PROTECTORPAIN;
  340.                 elif (worm[player].cause >= FIRSTMISSILE && worm[player].cause <= LASTMISSILE)
  341.                     pain = MISSILEPAIN;
  342.                 elif (worm[player].cause >= FIRSTDRIP && worm[player].cause <= LASTDRIP)
  343.                     pain = DRIPPAIN;
  344.                 else switch (worm[player].cause)
  345.                 {
  346.                 case BOMB:
  347.                     pain = BOMBPAIN;
  348.                 break;
  349.                 case WOOD:
  350.                     pain = WOODPAIN;
  351.                     slow = TRUE;
  352.                 break;
  353.                 case FRAGMENT:
  354.                     pain = FRAGMENTPAIN;
  355.                 break;
  356.                 case GOAT:
  357.                     pain = GOATPAIN;
  358.                     slow = TRUE;
  359.                 break;
  360.                 case SLAYER:
  361.                     pain = SLAYERPAIN;
  362.                 break;
  363.                 case STONE:
  364.                     pain = STONEPAIN;
  365.                     slow = TRUE;
  366.                 break;
  367.                 case TELEPORT:
  368.                     pain = TELEPORTPAIN;
  369.                     slow = TRUE;
  370.                 break;
  371.                 case SLIME:
  372.                     pain = SLIMEPAIN;
  373.                     slow = TRUE;
  374.                 break;
  375.                 case METAL:
  376.                     pain = METALPAIN;
  377.                     slow = TRUE;
  378.                 break;
  379.                 case REMNANTS:
  380.                     pain = REMNANTPAIN;
  381.                     slow = TRUE;
  382.                 break;
  383.                 case LIGHTNING:
  384.                     pain = LIGHTNINGPAIN;
  385.                 break;
  386.                 case PENGUIN:
  387.                     pain = PENGUINPAIN;
  388.                 break;
  389.                 case WHIRLWIND:
  390.                     pain = WHIRLWINDPAIN;
  391.                 break;
  392.                 case DOG:
  393.                     pain = DOGPAIN;
  394.                 break;
  395.                 case CLOUD:
  396.                     pain = CLOUDPAIN;
  397.                 break;
  398.                 default:
  399.                     /* assert(0); */
  400.                 break;
  401.                 }
  402.                 if (worm[player].victor >= 0 && worm[player].victor != player)
  403.                 {   wormscore(worm[player].victor, KILLWORM);
  404.                     if (worm[worm[player].victor].bias)
  405.                     {   worm[worm[player].victor].lives += pain;
  406.                         stat(worm[player].victor, LIFE);
  407.                 }   }
  408.                 if (slow)
  409.                 {   worm[player].speed = slowdown(worm[player].speed);
  410.                     stat(player, NITRO); 
  411.                 }
  412.                 if (pain > worm[player].lives)
  413.                     worm[player].lives = 0;
  414.                 else worm[player].lives -= pain;
  415.                 draw(worm[player].x, worm[player].y, SKULL);
  416.                 drawcause(player, NORMAL);
  417.                 stat(player, LIFE);
  418.                 if (level)
  419.                     worm[player].levelreached = level;
  420.                 else worm[player].levelreached = reallevel;
  421.                 if (worm[player].lives)
  422.                 {   effect(FXPAIN + player);
  423.                     worm[player].alive = TRUE;
  424.                     worm[player].causewait = r + CAUSEWAIT;
  425.                 } else
  426.                 {   /* kill worm */
  427.                     effect(FXWORMDEATH);
  428.                     if (ice == player)
  429.                         ice = -1;
  430.                     field[worm[player].x][worm[player].y] = SKULL;
  431.                     for (which = 0; which <= PROTECTORS; which++)
  432.                         if (protector[player][which].alive && protector[player][which].visible)
  433.                             change(protector[player][which].x, protector[player][which].y, EMPTY);
  434.                     for (which = 0; which <= MAGNETS; which++)
  435.                         if (player == magnet[which].player)
  436.                             magnet[which].alive = FALSE;
  437.                     if (worm[player].score >= worm[player].hiscore)
  438.                         worm[player].hiscore = worm[player].score;
  439.     }   }   }   }
  440.  
  441.     if (!worm[0].lives && !worm[1].lives && !worm[2].lives && !worm[3].lives)
  442.     {   /* End of game */
  443.         for (player = 0; player <= 3; player++)
  444.             if (worm[player].control != NONE && worm[player].score >= worm[player].hiscore)
  445.                 worm[player].hiscore = worm[player].score;
  446.         newhiscores();
  447.         effect(FXDEFEAT);
  448.         a = GAMEOVER;
  449.         if (players == 1)
  450.             say((STRPTR) "Game over!", worm[onlyworm(FALSE)].colour);
  451.         elif (worm[0].control && ((!worm[1].control) || worm[1].score < worm[0].score) && ((!worm[2].control) || worm[2].score < worm[0].score) && ((!worm[3].control) || worm[3].score < worm[0].score))
  452.             say((STRPTR) "Green wins!", GREEN);
  453.         elif (worm[1].control && ((!worm[0].control) || worm[0].score < worm[1].score) && ((!worm[2].control) || worm[2].score < worm[1].score) && ((!worm[3].control) || worm[3].score < worm[1].score))
  454.             say((STRPTR) "Red wins!", RED);
  455.         elif (worm[2].control && ((!worm[0].control) || worm[0].score < worm[2].score) && ((!worm[1].control) || worm[1].score < worm[2].score) && ((!worm[3].control) || worm[3].score < worm[2].score))
  456.             say((STRPTR) "Blue wins!", BLUE);
  457.         elif (worm[3].control && ((!worm[0].control) || worm[0].score < worm[3].score) && ((!worm[1].control) || worm[1].score < worm[3].score) && ((!worm[2].control) || worm[2].score < worm[3].score))
  458.             say((STRPTR) "Yellow wins!", YELLOW);
  459.         else say((STRPTR) "A draw!", WHITE);
  460.         waitasec();
  461.         anykey(FALSE);
  462. }   }
  463.  
  464. MODULE void drawcause(SBYTE player, SBYTE state)
  465. {    if (state == BLACK)
  466.         draw(-2 + ((FIELDX + 4) * worm[player].statx), (FIELDY / 2) - CAUSEYDISTANCE + (worm[player].staty * CAUSEYDISTANCE * 2), BLACKENED);
  467.     else draw(-2 + ((FIELDX + 4) * worm[player].statx), (FIELDY / 2) - CAUSEYDISTANCE + (worm[player].staty * CAUSEYDISTANCE * 2), worm[player].cause);
  468. }
  469.  
  470. MODULE void drawletter(SBYTE player, SBYTE letter, SBYTE state)
  471. {       UBYTE c;
  472.     
  473.     if (state == BLACK)
  474.                 c = BLACKENED;
  475.         else c = letter;
  476.     if (!worm[player].statx)
  477.         if (!worm[player].staty)
  478.             draw(-7 + ((letter - FIRSTLETTER) % 4),
  479.                 (FIELDY / 2) - 2 + ((letter - FIRSTLETTER) / 4),
  480.                                 c);
  481.         else
  482.             draw(-7 + ((letter - FIRSTLETTER) % 4),
  483.                 (FIELDY / 2) + 1 + ((letter - FIRSTLETTER) / 4),
  484.                                 c);
  485.     else
  486.         if (!worm[player].staty)
  487.             draw(FIELDX + 4 + ((letter - FIRSTLETTER) % 4),
  488.                 (FIELDY / 2) - 2 + ((letter - FIRSTLETTER) / 4),
  489.                                 c);
  490.             else
  491.                 draw(FIELDX + 4 + ((letter - FIRSTLETTER) % 4),
  492.                 (FIELDY / 2) + 1 + ((letter - FIRSTLETTER) / 4),
  493.                                 c);
  494. }
  495.  
  496. /* NAME     enginesetup -- once-only initialization of engine variables
  497. SYNOPSIS    enginesetup(void);
  498. FUNCTION    Sets up the unchanging worm variables.
  499. MODULE      engine.c */
  500.  
  501. void enginesetup(void)
  502. {       worm[0].statx = worm[0].staty = worm[1].staty = worm[2].statx = 0;
  503.     worm[1].statx = worm[2].staty = worm[3].statx = worm[3].staty = 1;
  504.     worm[0].colour    = GREEN;
  505.     worm[1].colour    = RED;
  506.     worm[2].colour    = BLUE;
  507.     worm[3].colour    = YELLOW;
  508.     worm[0].name[0] = worm[1].name[0] = worm[2].name[0] = worm[3].name[0] = 0;
  509.  
  510.         strcpy(pathname, DEFAULTSET);
  511.  
  512.     systemsetup();
  513. }
  514.  
  515. /* NAME     fastloop -- things done often
  516. SYNOPSIS    fastloop(void);
  517. FUNCTION    Checks for and handles level completion.
  518. MODULE      engine.c */
  519.  
  520. MODULE void fastloop(void)
  521. {    ABOOL    complete;
  522.     SBYTE    advancer = -1, player, which;
  523.  
  524.         /* update joystick `1' */
  525.         
  526.         joy0();
  527.  
  528.         /* flash letter */
  529.  
  530.         if (level)
  531.             if (r % 8 == 1)
  532.                 draw(letterx, lettery, WHITENED);
  533.             elif (r % 8 == 2)
  534.                 draw(letterx, lettery, lettertype);
  535.  
  536.         /* handle level completion */
  537.  
  538.     for (player = 0; player <= 3; player++)
  539.     {    complete = TRUE;
  540.         for (which = 0; which <= LETTERS; which++)
  541.             if (!letters[player][which])
  542.                 complete = FALSE;
  543.         if (complete)
  544.             advancer = player;
  545.     }
  546.     if (advancer != -1)
  547.     {    if (level++ == 0)
  548.         {    level = reallevel + 1;
  549.             reallevel = 0;
  550.         }
  551.         stopfx();
  552.         if (level > levels)
  553.             effect(FXVICTORY);
  554.         newlevel(advancer);
  555. }    }
  556.  
  557. void fillfield(SBYTE which)
  558. {    SBYTE x, y;
  559.  
  560.     for (x = 0; x <= FIELDX; x++)
  561.         for (y = 0; y <= FIELDY; y++)
  562.         {    board[level][x][y] = which;
  563.             draw(x, y, which);
  564.         }
  565.     board[level][startx[level]][starty[level]] = EMPTY;
  566.     draw(startx[level], starty[level], START);
  567.     if (teleport[level][0].alive)
  568.     {    board[level][teleport[level][0].x][teleport[level][0].y] = TELEPORT;
  569.         draw(teleport[level][0].x, teleport[level][0].y, ONE);
  570.     }
  571.     if (teleport[level][1].alive)
  572.     {    board[level][teleport[level][1].x][teleport[level][1].y] = TELEPORT;
  573.         draw(teleport[level][1].x, teleport[level][1].y, TWO);
  574. }    }
  575.  
  576. MODULE ABOOL findempty(SBYTE* x, SBYTE* y, SBYTE first, SBYTE last)
  577. {    SBYTE count = 0, xx, yy;
  578.  
  579.     do
  580.     {    xx = rand() % (FIELDX + 1);
  581.         yy = rand() % (FIELDY + 1);
  582.     } while ((field[xx][yy] < first || field[xx][yy] > last) && ++count < PATIENCE);
  583.     if (count < PATIENCE)
  584.     {    *x = xx;
  585.         *y = yy;
  586.         return(TRUE);
  587.     } else return(FALSE);
  588. }
  589.  
  590. void gameloop(void)
  591. {   SBYTE player, which;
  592.  
  593.     if (a == PLAYGAME)
  594.     {   fastloop();
  595.         gameinput();
  596.     }
  597.     if (a == PLAYGAME)
  598.         for (player = 0; player <= 3; player++)
  599.             if (worm[player].lives && (!(r % worm[player].speed)) && (ice == -1 || ice == player))
  600.                 wormloop(player);
  601.     if (a == PLAYGAME)
  602.         for (which = 0; which <= CREATURES; which++)
  603.             if (creature[which].alive && (!(r % creature[which].speed)) && (ice == -1 || (creature[which].species == MISSILE && ice == creature[which].type)))
  604.                 creatureloop(which);
  605.     if (a == PLAYGAME && !(r % MAGNETSPEED))
  606.         magnetloop();
  607.     if (a == PLAYGAME)
  608.         death();
  609.     if (a == PLAYGAME)
  610.         if (ice == -1 && (!(r % VERYSLOW)))
  611.             slowloop();
  612.         elif (--worm[ice].ice == 0)
  613.             ice = -1;
  614.     timing();
  615. }
  616.  
  617. MODULE void killall(void)
  618. {   UBYTE i;
  619.  
  620.     for (i = 0; i <= CREATURES; i++)
  621.         creature[i].alive = FALSE;
  622.     for (i = 0; i <= MAGNETS; i++)
  623.         magnet[i].alive = FALSE;
  624.     teleport[level][2].alive = FALSE;
  625.     teleport[level][3].alive = FALSE;
  626. }
  627.  
  628. void levelappend(void)
  629. {    UBYTE oldlevel;
  630.  
  631.     if (levels < MAXLEVELS)
  632.     {    oldlevel = level;
  633.         level = ++levels;
  634.         newfield();
  635.         level = oldlevel;
  636.         saylevel(WHITE);
  637. }    }
  638.  
  639. void leveldelete(void)
  640. {    SBYTE i;
  641.  
  642.     /* pull boards
  643.  */
  644.  
  645.     if (levels > 1)
  646.     {    if (level < levels)
  647.             for (i = level; i < levels; i++)
  648.                 copyfield(i + 1, i);
  649.         else
  650.             level--;
  651.         levels--;
  652.         saylevel(WHITE);
  653.         turborender();
  654. }    }
  655.  
  656. void levelerase(void)
  657. {    newfield();
  658.     turborender();
  659. }
  660.  
  661. void levelinsert(void)
  662. {    SBYTE i;
  663.  
  664.     /* push boards
  665.  */
  666.  
  667.     if (levels < MAXLEVELS)
  668.     {    for (i = levels; i >= level; i--)
  669.             copyfield(i, i + 1);
  670.         levels++;
  671.         saylevel(WHITE);
  672.         newfield();
  673.         turborender();
  674. }    }
  675.  
  676. SBYTE loadfields(STRPTR fieldname)
  677. {   SBYTE i, j, x, y;
  678.     TEXT  IOBuffer[NAMELENGTH + 1];
  679.     UBYTE ver;
  680.  
  681.     /* This routine is not entirely robust, especially regarding
  682.     failures part way through reading. Also, field data values must be
  683.     those supported by the field editor (ie. objects, and the squares
  684.     represented by F1-F8), or undefined behaviour may result. None of
  685.     this is currently checked for. Provided that the fieldset was
  686.     created with the official field editor, and the file is not
  687.     corrupt, these failures should never happen anyway.
  688.  
  689.     open file */
  690.  
  691.     if (!ZOpen(fieldname, FALSE))
  692.         return 1; /* no harm done */
  693.  
  694.     /* read header */
  695.  
  696.     if (!ZRead(IOBuffer, 10))
  697.     {    ZClose();
  698.         return 2; /* no harm done */
  699.     }
  700.     if (!strcmp(IOBuffer, "FSET 5.6"))
  701.         ver = 56;
  702.     elif (!strcmp(IOBuffer, "FSET 5.5"))
  703.         ver = 55;
  704.     elif (!strcmp(IOBuffer, "FSET 5.3"))
  705.         ver = 53;
  706.     elif (!strcmp(IOBuffer, "FSET 5.1"))
  707.         ver = 51;
  708.     elif (!strcmp(IOBuffer, "FSET 5.0"))
  709.         ver = 50;
  710.     elif (!strcmp(IOBuffer, "FSET 4.4"))
  711.         ver = 44;
  712.     else
  713.     {   ZClose();
  714.         return 3; /* no harm done */
  715.     }
  716.     levels = IOBuffer[9];
  717.  
  718.     /* read high score table */
  719.  
  720.     for (i = 0; i <= HISCORES; i++)
  721.     {    if (!ZRead(IOBuffer, 6))
  722.         {    ZClose();
  723.             return 4; /* incorrect levels */
  724.         }
  725.         hiscore[i].fresh            =  FALSE;
  726.         hiscore[i].player            =  IOBuffer[0];
  727.         hiscore[i].level            =  IOBuffer[1];
  728.         hiscore[i].score            = (IOBuffer[3] * 65536)
  729.                                     + (IOBuffer[4] * 256)
  730.                                     +  IOBuffer[5];
  731.  
  732.         if (!ZRead(IOBuffer, NAMELENGTH + 1))
  733.         {    ZClose();
  734.             return 5; /* incorrect levels, corrupted high scores */
  735.         }
  736.         for (j = 0; j <= NAMELENGTH; j++)
  737.             hiscore[i].name[j]        = IOBuffer[j];
  738.  
  739.         if (ver >= 50)
  740.         {    if (!ZRead(IOBuffer, TIMELENGTH + 1))
  741.             {    ZClose();
  742.                 return 6; /* incorrect levels, corrupted high scores */
  743.             }
  744.             for (j = 0; j <= TIMELENGTH; j++)
  745.                 hiscore[i].time[j]    = IOBuffer[j];
  746.  
  747.             if (!ZRead(IOBuffer, DATELENGTH + 1))
  748.             {    ZClose();
  749.                 return 7; /* incorrect levels, corrupted high scores */
  750.             }
  751.             for (j = 0; j <= DATELENGTH; j++)
  752.                 hiscore[i].date[j]    = IOBuffer[j];
  753.         } else
  754.         {    /* skip extra name character */
  755.  
  756.             if (!ZRead(IOBuffer, 1))
  757.             {    ZClose();
  758.                 return 8; /* incorrect levels, corrupted high scores */
  759.             } else
  760.             {    if (hiscore[i].name[0])
  761.                 {    strcpy(hiscore[i].time, "??:??");
  762.                     strcpy(hiscore[i].date, "??/??/??");
  763.                 } else
  764.                 {    hiscore[i].time[0] = 0;
  765.                     hiscore[i].date[0] = 0;
  766.     }    }    }    }
  767.  
  768.     /* read level data */
  769.  
  770.     for (i = 0; i <= levels; i++)
  771.     {   if (!ZRead(IOBuffer, 8))
  772.         {   ZClose();
  773.             return 9;
  774.             /* incorrect levels, corrupted high scores,
  775.             incorrect startx, teleports, field data */
  776.         }
  777.         startx[i]            =  IOBuffer[0];
  778.         starty[i]            =  IOBuffer[1];
  779.         teleport[i][0].alive =  IOBuffer[2];
  780.         teleport[i][0].x     =  IOBuffer[3];
  781.         teleport[i][0].y     =  IOBuffer[4];
  782.         teleport[i][1].alive =  IOBuffer[5];
  783.         teleport[i][1].x     =  IOBuffer[6];
  784.         teleport[i][1].y     =  IOBuffer[7];
  785.  
  786.         if (!ZRead((char *) &board[i][0][0], (FIELDX + 1) * (FIELDY + 1)))
  787.         {   ZClose();
  788.             return 10;
  789.             /* incorrect levels, corrupted high scores,
  790.             incorrect startx, teleports, field data */
  791.         } else
  792.         {   if (ver <= 44)
  793.             {   // convert from FSET 4.4 to FSET 5.0 format
  794.                 for (x = 0; x <= FIELDX; x++)
  795.                     for (y = 0; y <= FIELDY; y++)
  796.                         if (board[i][x][y] >= 16)
  797.                             board[i][x][y] += 2;
  798.             }
  799.             if (ver <= 50)
  800.             {   // convert from FSET 5.0 to FSET 5.1 format
  801.                 for (x = 0; x <= FIELDX; x++)
  802.                      for (y = 0; y <= FIELDY; y++)
  803.                           if (board[i][x][y] >= 11)
  804.                               board[i][x][y]++;
  805.             }
  806.             if (ver <= 51)
  807.             {   // convert from FSET 5.1 to FSET 5.3 format
  808.                 for (x = 0; x <= FIELDX; x++)
  809.                     for (y = 0; y <= FIELDY; y++)
  810.                         if (board[i][x][y] >= 7 && board[i][x][y] <= 63)
  811.                             board[i][x][y]++;
  812.             }
  813.             if (ver <= 53)
  814.             {   // convert from FSET 5.3 to FSET 5.5 format
  815.                 for (x = 0; x <= FIELDX; x++)
  816.                     for (y = 0; y <= FIELDY; y++)
  817.                         if (board[i][x][y] >= 20)
  818.                             board[i][x][y]++;
  819.             }
  820.             if (ver <= 55)
  821.             {   // convert from FSET 5.5 to FSET 5.6 format
  822.                 for (x = 0; x <= FIELDX; x++)
  823.                     for (y = 0; y <= FIELDY; y++)
  824.                         if (board[i][x][y] >= 13)
  825.                             board[i][x][y]++;
  826.     }   }   }
  827.  
  828.     // no need to read version string
  829.     ZClose();
  830.     modified = FALSE;
  831.     return 0;
  832. }
  833.  
  834. void matchteleports(void)
  835. {    SBYTE which;
  836.  
  837.     for (which = 0; which <= levels; which++)
  838.         if (teleport[which][0].alive == TRUE && teleport[which][1].alive == FALSE)
  839.         {    board[which][teleport[which][0].x][teleport[which][0].y] = EMPTY;
  840.             teleport[which][0].alive = FALSE;
  841.             if (level == which && a == FIELDEDIT)
  842.                 draw(teleport[which][0].x, teleport[which][0].y, EMPTY);
  843.         } elif (teleport[which][0].alive == FALSE && teleport[which][1].alive == TRUE)
  844.         {    board[which][teleport[which][1].x][teleport[which][1].y] = EMPTY;
  845.             teleport[which][1].alive = FALSE;
  846.             if (level == which && a == FIELDEDIT)
  847.                 draw(teleport[which][1].x, teleport[which][1].y, EMPTY);
  848. }        }
  849.  
  850. MODULE void newfield(void)
  851. {    int x, y;
  852.  
  853.     teleport[level][0].alive = FALSE;
  854.     teleport[level][1].alive = FALSE;
  855.     startx[level] = FIELDX / 2;
  856.     starty[level] = FIELDY / 2;
  857.  
  858.     if (level)
  859.         for (x = 0; x <= FIELDX; x++)
  860.             for (y = 0; y <= FIELDY; y++)
  861.                 board[level][x][y] = EMPTY;
  862.     else for (x = 0; x <= FIELDX; x++)
  863.         for (y = 0; y <= FIELDY; y++)
  864.             board[0][x][y] = SILVER;
  865. }
  866.  
  867. void newfields(void)
  868. {   if (verify())
  869.     {   strcpy(pathname, DEFAULTSET);
  870.         levels = DEFAULTLEVELS;
  871.         modified = FALSE;
  872.         for (level = 0; level <= levels; level++)
  873.             newfield();
  874.         clearhiscores();
  875.         level = 1;
  876.         if (a == FIELDEDIT)
  877.         {    turborender();
  878.             saylevel(WHITE);
  879.         } else hiscores();
  880. }    }
  881.  
  882. void newgame(void)
  883. {    SBYTE player;
  884.  
  885.     players = 0;
  886.     for (player = 0; player <= 3; player++)
  887.         if (worm[player].control != NONE)
  888.             players++;
  889.  
  890.     for (player = 0; player <= 3; player++)
  891.     {    worm[player].lives = 0;
  892.         worm[player].speed = NORMAL;
  893.         worm[player].hiscore = 0;
  894.     }
  895.  
  896.     r            = -1;
  897.     trainer        = FALSE;
  898.     ice            = -1;
  899.     reallevel    = 0;
  900.  
  901.     level        = 1;
  902.     a            = PLAYGAME;
  903.     clearscreen();
  904.     newlevel(rand() % 4);
  905.     timing();
  906. }
  907.  
  908. MODULE void newhiscores(void)
  909. {   PERSIST TEXT  amiganame[4][NAMELENGTH + 1] = {"Jay Miner", "Carl Sassenrath", "R. J. Mical", "Dave Morse"};
  910.     AUTO    SBYTE i, j, player;
  911.  
  912.     datestamp();
  913.     for (player = 0; player <= 3; player++)
  914.         for (i = 0; i <= HISCORES; i++)
  915.             if (worm[player].control != NONE && worm[player].score >= hiscore[i].score)
  916.             {   /* push all worse hiscores down */
  917.  
  918.                 if (i < HISCORES)
  919.                     for (j = HISCORES; j >= i + 1; j--)
  920.                     {    hiscore[j].player      = hiscore[j - 1].player;
  921.                         hiscore[j].score      = hiscore[j - 1].score;
  922.                         hiscore[j].level      = hiscore[j - 1].level;
  923.                         hiscore[j].fresh      = hiscore[j - 1].fresh;
  924.                         strcpy(hiscore[j].name, hiscore[j - 1].name);
  925.                         strcpy(hiscore[j].date, hiscore[j - 1].date);
  926.                         strcpy(hiscore[j].time, hiscore[j - 1].time);
  927.                     }
  928.                 modified = TRUE;
  929.                 hiscore[i].player = player;
  930.                 hiscore[i].score = worm[player].hiscore;
  931.                 hiscore[i].level = worm[player].levelreached;
  932.                 if (worm[player].control == AMIGA)
  933.                 {    strcpy(hiscore[i].name, amiganame[player]);
  934.                     hiscore[i].fresh = FALSE;
  935.                 } else
  936.                 {    strcpy(hiscore[i].name, "(New)");
  937.                     hiscore[i].fresh = TRUE;
  938.                 }
  939.                 strcpy(hiscore[i].time, times);
  940.                 strcpy(hiscore[i].date, date);
  941.                 break; /* vital
  942.  */
  943. }            }
  944.  
  945. MODULE void newlevel(SBYTE player)
  946. {   SBYTE iwhich, which;
  947.  
  948.     if (level >= 2 && worm[player].lives)
  949.         rundown(player);
  950.     if (a == PLAYGAME)
  951.     {   if (level > levels)
  952.         {   for (which = 0; which <= 3; which++)
  953.                 if (worm[which].lives)
  954.                     worm[which].levelreached = -1;
  955.             celebrate();
  956.             newhiscores();
  957.             titlescreen();
  958.         } else
  959.         {   saylevel(WHITE);
  960.             for (which = 0; which <= 3; which++)
  961.                 worm[which].multi = (SBYTE) atleast(worm[which].multi / 2, 1);
  962.             killall();
  963.             clearletters();
  964.             orientworms();
  965.             changefield();
  966.             turborender();
  967.             delay = atleast(DELAY_MAX - (level * DELAY_DEC), DELAY_MIN);
  968.  
  969.                     if (level)
  970.                     {   secondsperlevel = SECONDSPERLEVEL;
  971.                         putletter(-1);
  972.                         freq = (SBYTE) atleast(FREQ_MAX - ((level - 1) * FREQ_DEC), FREQ_MIN);
  973.                         for (which = 0; which <= 3; which++)
  974.                 {   if (!worm[which].lives && worm[which].control != NONE)
  975.                             {   /* create (or resurrect) a worm
  976.  */
  977.  
  978.                                 worm[which].lives      = STARTLIVES;
  979.                                 worm[which].score      = 0;
  980.                                 worm[which].alive      = TRUE;
  981.                                 worm[which].oldscore   = 0;
  982.                                 worm[which].armour     = 0;
  983.                                 worm[which].tongue     = 0;
  984.                                 worm[which].nitro      = FALSE;
  985.                                 worm[which].mode       = NULL;
  986.                                 worm[which].power      = 0;
  987.                                 worm[which].bias       = 0;
  988.                                 worm[which].multi      = 1;
  989.                                 worm[which].ice        = 0;
  990.                                 worm[which].victor     = -1;
  991.                                 worm[which].ammo       = 0;
  992.                                 worm[which].remnants   = FALSE;
  993.                                 worm[which].affixer    = FALSE;
  994.                                 worm[which].sideshot   = FALSE;
  995.                                 worm[which].causewait  = (ULONG) -1;
  996.                                 worm[which].last       = FIRSTTAIL + which;
  997.                                 worm[which].pos        = -1;
  998.                                 for (iwhich = 0; iwhich <= PROTECTORS; iwhich++)
  999.                                     protector[which][iwhich].alive = FALSE;
  1000.                                 for (iwhich = 0; iwhich <= LASTOBJECT; iwhich++)
  1001.                                     stat(which, iwhich);
  1002.     }   }   }   }   }
  1003.     clearjoystick();
  1004.     clearkybd();
  1005.     resettime();
  1006. }
  1007.  
  1008. MODULE void explosion(SBYTE x, SBYTE y, SBYTE exceptionx, SBYTE exceptiony)
  1009. {   UBYTE i, generated = 0;
  1010.  
  1011. /* You wouldn't think this would work properly for pulse-explosions,
  1012. because the worm's head is obliterated. However, it is refreshed (as
  1013. tail) the next time wormloop() is called for that worm. */
  1014.  
  1015.     effect(FXEXPLODE);
  1016.     for (i = 0; i <= CREATURES; i++)
  1017.         if ((!(creature[i].alive)) && generated <= 7)
  1018.         {   creature[i].last      = EMPTY;
  1019.             creature[i].x         = x;
  1020.             creature[i].y         = y;
  1021.             if (level)
  1022.                 creature[i].speed = (SBYTE) atleast(FRAGSPEED - (level / 2), 1);
  1023.             else creature[i].speed = BONUSFRAGSPEED;
  1024.         creature[i].species   = FRAGMENT;
  1025.             creature[i].visible   = TRUE;
  1026.             switch (generated)
  1027.             {
  1028.             case 0:
  1029.                 creature[i].deltax = 0;
  1030.                 creature[i].deltay = -1;
  1031.             break;
  1032.             case 1:
  1033.                 creature[i].deltax = 1;
  1034.                 creature[i].deltay = -1;
  1035.             break;
  1036.             case 2:
  1037.                 creature[i].deltax = 1;
  1038.                 creature[i].deltay = 0;
  1039.             break;
  1040.             case 3:
  1041.                 creature[i].deltax = 1;
  1042.                 creature[i].deltay = 1;
  1043.             break;
  1044.             case 4:
  1045.                 creature[i].deltax = 0;
  1046.                 creature[i].deltay = 1;
  1047.             break;
  1048.             case 5:
  1049.                 creature[i].deltax = -1;
  1050.                 creature[i].deltay = 1;
  1051.             break;
  1052.             case 6:
  1053.                 creature[i].deltax = -1;
  1054.                 creature[i].deltay = 0;
  1055.             break;
  1056.             case 7:
  1057.                 creature[i].deltax = -1;
  1058.                 creature[i].deltay = -1;
  1059.             break;
  1060.         default:
  1061.             break;
  1062.         }
  1063.     generated++;
  1064.         if (creature[i].deltax != exceptionx || creature[i].deltay != exceptiony)
  1065.         {   creature[i].alive = TRUE;
  1066.             if (generated == 1)
  1067.             change(x, y, FRAGMENT);
  1068. }   }   }
  1069.  
  1070. /* Many creatures take advantage of shared characteristics.
  1071. 10 creature types (orbs, goats, drips, fragments, missiles, penguins,
  1072. cyclones, dogs, clouds, timebombs) use the creature structure.
  1073. Independent of it are worms, protectors, worm bullets and teleports. */
  1074.  
  1075. MODULE void creatureloop(SBYTE which)
  1076. {   ABOOL   happy = FALSE;
  1077.     UBYTE   bestdistance = 255, distance, player, c, i;
  1078.     SBYTE   x, y, xx, yy, xxx, yyy, frontx, fronty, rearx, reary;
  1079.  
  1080. x = creature[which].x;
  1081. y = creature[which].y;
  1082.  
  1083. if (creature[which].species == ORB && creature[which].explode)
  1084. {   creature[which].alive = FALSE;
  1085.     explosion(x, y, -2, -2);
  1086.     return;
  1087. }
  1088.  
  1089. /* decide whether and where to move
  1090.  */
  1091.  
  1092. switch(creature[which].species)
  1093. {
  1094. case CLOUD:
  1095.         if (creature[which].x == 0 || creature[which].x == FIELDX)
  1096.             creature[which].deltax = -creature[which].deltax;
  1097. break;
  1098. case TIMEBOMB:
  1099.     /* decrement and explode timebombs */
  1100.         if (field[x][y] != TIMEBOMB)
  1101.             creature[which].alive = FALSE;
  1102.         else
  1103.         {   effect(FXTIMEBOMBTICK);
  1104.             creature[which].time--;
  1105.             if (creature[which].time < 0)
  1106.             {   creature[which].alive = FALSE;
  1107.                 bombblast(BOMB, 0, x, y);
  1108.                 change(x, y, EMPTY);
  1109.             } else draw(x, y, ZERO + creature[which].time);
  1110.         }
  1111.         return;
  1112. break;
  1113. case DOG:
  1114.         /* remove a movement from the dog queue */
  1115.  
  1116.         if (creature[which].dormant == CHASING)
  1117.         {   if (creature[which].pos != -1)
  1118.             {   creature[which].deltax = thedogqueue[which][0].deltax;
  1119.                 creature[which].deltay = thedogqueue[which][0].deltay;
  1120.                 if (--creature[which].pos != -1)
  1121.                 {   for (i = 0; i <= creature[which].pos; i++)
  1122.                     {   thedogqueue[which][i].deltax = thedogqueue[which][i + 1].deltax;
  1123.                         thedogqueue[which][i].deltay = thedogqueue[which][i + 1].deltay;
  1124.             }   }   }
  1125.             else creature[which].alive = FALSE;
  1126.         }
  1127. break;
  1128. case PENGUIN:
  1129.     do
  1130.     {    xx = (rand() % 3) - 1;
  1131.         yy = (rand() % 3) - 1;
  1132.     } while (!valid(x + xx, y + yy));
  1133.         c = field[x + xx][y + yy];
  1134.         if (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1135.     {    creature[which].deltax = xx;
  1136.         creature[which].deltay = yy;
  1137.     } else
  1138.     {    creature[which].deltax = 0;
  1139.         creature[which].deltay = 0;
  1140.     }
  1141. break;
  1142. case WHIRLWIND:
  1143.     /* Whirlwinds has a slight upwards drift.
  1144.     Higher values of UNDRIFT make it less buoyant. */
  1145.  
  1146.     creature[which].deltax = (rand() % 3) - 1;
  1147.     if (!(rand() % UNDRIFT))
  1148.         creature[which].deltay = (rand() % 2) - 1;
  1149.     else creature[which].deltay = (rand() % 3) - 1;
  1150. break;
  1151. case MISSILE:
  1152.     for (player = 0; player <= 3; player++)
  1153.         if (creature[which].type != player && worm[player].lives && !worm[player].bias)
  1154.         {   xx = abs(worm[player].x - x);
  1155.             yy = abs(worm[player].y - y);
  1156.             if (xx < yy)
  1157.                 distance = xx;
  1158.             else distance = yy;
  1159.             if (distance <= bestdistance)
  1160.             {   bestdistance = distance;
  1161.                 creature[which].deltax = bsign(worm[player].x - x);
  1162.                 creature[which].deltay = bsign(worm[player].y - y);
  1163.         }   }
  1164.     for (i = 0; i <= CREATURES; i++)
  1165.         if (creature[i].alive && which != i)
  1166.         {   if
  1167.             (   creature[i].species == ORB
  1168.             ||  (creature[i].species == MISSILE && creature[i].type != creature[which].type)
  1169.             ||  creature[i].species == GOAT
  1170.             )
  1171.             {   xx = abs(creature[i].x - x);
  1172.                 yy = abs(creature[i].y - y);
  1173.                 if (xx < yy)
  1174.                     distance = xx;
  1175.                 else distance = yy;
  1176.                 if (distance <= bestdistance)
  1177.                 {   bestdistance = distance;
  1178.                     creature[which].deltax = bsign(creature[i].x - x);
  1179.                     creature[which].deltay = bsign(creature[i].y - y);
  1180.         }   }   }
  1181.     if (bestdistance == 255)
  1182.         creature[which].alive = FALSE;
  1183. break;
  1184. case ORB:
  1185.     frontx  = xwrap(x + creature[which].deltax);  /* look in front */
  1186.     fronty  = ywrap(y + creature[which].deltay);
  1187.     rearx   = xwrap(x - creature[which].deltax);  /* look behind */
  1188.     reary   = ywrap(y - creature[which].deltay);
  1189.     if (bounceorb(which, frontx, fronty))
  1190.     {   bouncegoat(which, frontx, fronty);
  1191.         xx = -creature[which].deltax; /* default bounce angle is 180° */
  1192.         yy = -creature[which].deltay;
  1193.         if (!bounceorb(which, frontx, reary))
  1194.         {    if (bounceorb(which, rearx, fronty))
  1195.             {   bouncegoat(which, rearx, fronty);
  1196.                 xx = creature[which].deltax;
  1197.         }    }
  1198.         elif (!bounceorb(which, rearx, fronty))
  1199.         {   bouncegoat(which, rearx, fronty);
  1200.             yy = creature[which].deltay;
  1201.         }
  1202.         creature[which].deltax = xx;
  1203.         creature[which].deltay = yy;
  1204.     }
  1205. break;
  1206. case GOAT:
  1207.     /* decide whether to move
  1208.  */
  1209.     if (!(rand() % GOATMOVE))
  1210.     {   for (xx = x - 1; xx <= x + 1; xx++)
  1211.             for (yy = y - 1; yy <= y + 1; yy++)
  1212.                 if (valid(xx, yy) && field[xx][yy] >= FIRSTEMPTY && field[xx][yy] <= LASTEMPTY)
  1213.                 {   happy = TRUE;
  1214.                     break;
  1215.     }            }
  1216.     creature[which].deltax = 0;
  1217.     creature[which].deltay = 0;
  1218.     if (!happy)
  1219.     {    xx = (rand() % 3) - 1;
  1220.         yy = (rand() % 3) - 1;
  1221.         if (valid(x + xx, y + yy) && (xx || yy))
  1222.                 {       c = field[x + xx][y + yy];
  1223.             if (c >= FIRSTGOAT && c <= LASTGOAT && c != GOAT)
  1224.             {    creature[which].last = creature[which].oldlast;
  1225.                                 creature[which].oldlast = c;
  1226.                 creature[which].deltax = xx;
  1227.                 creature[which].deltay = yy;
  1228.     }    }    }
  1229. break;
  1230. default:
  1231. break;
  1232. }
  1233.  
  1234. /* now move */
  1235.  
  1236. if (creature[which].deltax || creature[which].deltay)
  1237. {    if (creature[which].visible)
  1238.     {   /* erase previous image */
  1239.         change(x, y, creature[which].last);
  1240.         if (creature[which].species != FRAGMENT)
  1241.             creature[which].last = EMPTY;
  1242.     }
  1243.     if (creature[which].alive)
  1244.     {   creature[which].x += creature[which].deltax;
  1245.         creature[which].y += creature[which].deltay;
  1246.         if (creature[which].species == ORB)
  1247.         {   creature[which].x = xwrap(creature[which].x);
  1248.             creature[which].y = ywrap(creature[which].y);
  1249.         } elif (creature[which].species == FRAGMENT || creature[which].species == DRIP || creature[which].species == WHIRLWIND || creature[which].species == DOG)
  1250.         {    if (!valid(creature[which].x, creature[which].y))
  1251.            creature[which].alive = FALSE;
  1252. }    }   }
  1253.  
  1254. creature[which].visible = TRUE;
  1255. x = creature[which].x;
  1256. y = creature[which].y;
  1257.  
  1258. /* Collision detection.
  1259. Goats, penguins, timebombs don't need to go through this. */
  1260.  
  1261. if
  1262. (    creature[which].alive
  1263. &&    creature[which].species != GOAT
  1264. &&    creature[which].species != PENGUIN
  1265. &&    (creature[which].deltax || creature[which].deltay)
  1266. )
  1267. {       c = field[x][y];
  1268.  
  1269.     if (c >= FIRSTHEAD && c <= LASTHEAD)
  1270.     {   if (creature[which].species == MISSILE)
  1271.             wormmissile(x, y, c - FIRSTHEAD, which);
  1272.         elif (creature[which].species == DOG)
  1273.             wormdog(x, y, c - FIRSTHEAD, which);
  1274.         elif (creature[which].species == FRAGMENT)
  1275.             wormfrag(x, y, c - FIRSTHEAD, which);
  1276.         elif (creature[which].species == DRIP)
  1277.             wormdrip(x, y, c - FIRSTHEAD, which);
  1278.         elif (creature[which].species == WHIRLWIND)
  1279.             wormwhirlwind(x, y, c - FIRSTHEAD, which);
  1280.         elif (creature[which].species == CLOUD)
  1281.             cloudworm(x, y, which, c - FIRSTHEAD);
  1282.         elif (creature[which].species == ORB)
  1283.         {   wormorb(x, y, c - FIRSTHEAD, which);
  1284.             creature[which].last = c - FIRSTHEAD + FIRSTTAIL; /* note sign issues */
  1285.     }   }
  1286.     elif (c == TIMEBOMB)
  1287.     {   creature[whichcreature(x, y, which, TIMEBOMB)].alive = FALSE;
  1288.         bombblast(BOMB, 0, x, y);
  1289.         change(x, y, EMPTY);
  1290.     } elif (c >= FIRSTTAIL && c <= LASTTAIL)
  1291.     {   if (creature[which].species == ORB)
  1292.         {   if (creature[which].mode == TONGUE)
  1293.                 effect(FXUSETONGUE);
  1294.             else
  1295.             {   if (worm[c - FIRSTTAIL].alive)
  1296.                 {   effect(FXORBDEATH);
  1297.                     wormscore(c - FIRSTTAIL, creature[which].score);
  1298.                     if (worm[c - FIRSTTAIL].bias)
  1299.                     {   worm[c - FIRSTTAIL].lives += ORBBLOOD;
  1300.                         stat(c - FIRSTTAIL, LIFE);
  1301.                 }   }
  1302.                 creature[which].alive = FALSE;
  1303.                 change(x, y, BONUS);
  1304.     }   }   }
  1305.     elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  1306.     {   if (creature[which].species == DOG)
  1307.             protdog(x, y, c - FIRSTPROTECTOR, which);
  1308.         elif (creature[which].species == DRIP)
  1309.             protdrip(x, y, c - FIRSTPROTECTOR, which);
  1310.         elif (creature[which].species == MISSILE)
  1311.             protmissile(x, y, c - FIRSTPROTECTOR, which);
  1312.         elif (creature[which].species == FRAGMENT)
  1313.             protfrag(x, y, c - FIRSTPROTECTOR, which);
  1314.         elif (creature[which].species == ORB)
  1315.             protorb(x, y, c - FIRSTPROTECTOR, which);
  1316.         elif (creature[which].species == PENGUIN)
  1317.             protpenguin(x, y, c - FIRSTPROTECTOR, which);
  1318.         elif (creature[which].species == WHIRLWIND)
  1319.             protwhirlwind(x, y, c - FIRSTPROTECTOR, which);
  1320.         elif (creature[which].species == CLOUD)
  1321.             cloudprot(x, y, which, c - FIRSTPROTECTOR);
  1322.     } elif (c >= FIRSTLETTER && c <= LASTLETTER)
  1323.     {   if (creature[which].species == DRIP || creature[which].species == FRAGMENT || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1324.         {   effect(FXTHUD);
  1325.             creature[which].alive = FALSE;
  1326.         } elif (creature[which].species == ORB)
  1327.         {   for (player = 0; player <= 3; player++)
  1328.             {   letters[player][c - FIRSTLETTER] = FALSE;
  1329.                 drawletter(player, c, BLACK);
  1330.             }
  1331.             putletter(-1);
  1332.             orbscore(which, LETTERPOINT);
  1333.         } elif (creature[which].species == WHIRLWIND)
  1334.             putletter(-1);
  1335.     } elif (c >= FIRSTDRIP && c <= LASTDRIP)
  1336.     {   i = whichcreature(x, y, DRIP, which);
  1337.         if (creature[which].species == FRAGMENT)
  1338.             dripfrag(x, y, i, which);
  1339.         elif (creature[which].species == MISSILE)
  1340.             dripmissile(x, y, i, which);
  1341.         elif (creature[which].species == ORB)
  1342.             driporb(x, y, i, which);
  1343.         elif (creature[which].species == WHIRLWIND)
  1344.             dripwhirlwind(x, y, i, which);
  1345.         elif (creature[which].species == CLOUD)
  1346.             clouddrip(x, y, which, i);
  1347.     } elif (c >= FIRSTMISSILE && c <= LASTMISSILE)
  1348.     {   i = whichcreature(x, y, MISSILE, which);
  1349.         if (creature[which].species == FRAGMENT)
  1350.             fragmissile(x, y, which, i);
  1351.         elif (creature[which].species == DRIP)
  1352.             dripmissile(x, y, which, i);
  1353.         elif (creature[which].species == ORB)
  1354.             orbmissile(x, y, which, i);
  1355.         elif (creature[which].species == WHIRLWIND)
  1356.             missilewhirlwind(x, y, i, which);
  1357.         elif (creature[which].species == MISSILE)
  1358.             missilemissile(x, y, which, i);
  1359.         elif (creature[which].species == CLOUD)
  1360.             cloudmissile(x, y, which, i);
  1361.     } elif (c == WHIRLWIND)
  1362.     {   i = whichcreature(x, y, WHIRLWIND, which);
  1363.         if (creature[which].species == DRIP)
  1364.             dripwhirlwind(x, y, which, i);
  1365.         elif (creature[which].species == MISSILE)
  1366.             missilewhirlwind(x, y, which, i);
  1367.         elif (creature[which].species == ORB)
  1368.             orbwhirlwind(x, y, which, i);
  1369.         elif (creature[which].species == WHIRLWIND)
  1370.             whirlwindwhirlwind(x, y, which, i);
  1371.         elif (creature[which].species == FRAGMENT)
  1372.             fragwhirlwind(x, y, which, i);
  1373.         elif (creature[which].species == CLOUD)
  1374.             cloudwhirlwind(x, y, which, i);
  1375.     } elif (c == DOG)
  1376.     {   i = whichcreature(x, y, DOG, which);
  1377.         if (creature[which].species == FRAGMENT)
  1378.             dogfrag(x, y, i, which);
  1379.         elif (creature[which].species == PENGUIN)
  1380.             dogpenguin(x, y, i, which);
  1381.         elif (creature[which].species == ORB)
  1382.             dogorb(x, y, i, which);
  1383.         elif (creature[i].species == DRIP)
  1384.             dogdrip(x, y, i, which);
  1385.         elif (creature[i].species == WHIRLWIND)
  1386.             dogwhirlwind(x, y, i, which);
  1387.         elif (creature[i].species == MISSILE)
  1388.             dogmissile(x, y, i, which);
  1389.         elif (creature[i].species == DOG)
  1390.             dogdog(x, y, i, which);
  1391.         elif (creature[i].species == CLOUD)
  1392.             clouddog(x, y, which, i);
  1393.     } elif (c == PENGUIN)
  1394.     {   i = whichcreature(x, y, PENGUIN, which);
  1395.         if (creature[which].species == ORB)
  1396.             orbpenguin(x, y, which, i);
  1397.         elif (creature[which].species == DOG)
  1398.             dogpenguin(x, y, which, i);
  1399.         elif (creature[which].species == WHIRLWIND)
  1400.             penguinwhirlwind(x, y, i, which);
  1401.         elif (creature[which].species == MISSILE)
  1402.             missilepenguin(x, y, which, i);
  1403.         elif (creature[which].species == DRIP)
  1404.             drippenguin(x, y, which, i);
  1405.         elif (creature[which].species == CLOUD)
  1406.             cloudpenguin(x, y, which, i);
  1407.     } elif (c == FRAGMENT)
  1408.     {   i = whichcreature(x, y, FRAGMENT, which);
  1409.         if (creature[which].species == MISSILE)
  1410.             fragmissile(x, y, i, which);
  1411.         elif (creature[which].species == DRIP)
  1412.             dripfrag(x, y, which, i);
  1413.         elif (creature[which].species == ORB)
  1414.             fragorb(x, y, i, which);
  1415.         elif (creature[which].species == FRAGMENT)
  1416.             fragfrag(x, y, which, i);
  1417.         elif (creature[which].species == WHIRLWIND)
  1418.             fragwhirlwind(x, y, i, which);
  1419.         elif (creature[which].species == CLOUD)
  1420.             cloudfrag(x, y, which, i);
  1421.         elif (creature[which].species == DOG)
  1422.             dogfrag(x, y, which, i);
  1423.     } elif (c == METAL)
  1424.     {   if (creature[which].species == DRIP || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1425.             creature[which].alive = FALSE;
  1426.         elif (creature[which].species == FRAGMENT)
  1427.             reflect(which);
  1428.     } elif (c == STONE)
  1429.     {   if (creature[which].species == DRIP || creature[which].species == FRAGMENT || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1430.         {   effect(FXTHUD);
  1431.             creature[which].alive = FALSE;
  1432.     }   }
  1433.     elif (c == WOOD)
  1434.     {   if (creature[which].species == FRAGMENT || creature[which].species == MISSILE || creature[which].species == CLOUD || creature[which].species == DRIP)
  1435.         {   effect(FXTHUD);
  1436.             creature[which].alive = FALSE;
  1437.     }   }
  1438.     elif (c == GOAT)
  1439.     {   /* Drips, fragments, missiles, cyclones, dogs, clouds */
  1440.         creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  1441.         effect(FXGOATDEATH);
  1442.         if (creature[which].species != WHIRLWIND)
  1443.         {   creature[which].alive = FALSE;
  1444.             change(x, y, BONUS);
  1445.         }
  1446.         if (creature[which].species == MISSILE)
  1447.         {   wormscore(creature[which].type, KILLGOAT);
  1448.             if (worm[creature[which].type].bias)
  1449.             {   worm[creature[which].type].lives += GOATBLOOD;
  1450.                 stat(creature[which].type, LIFE);
  1451.     }   }   }
  1452.     elif (c == SLIME)
  1453.     {   if (creature[which].species == DRIP || creature[which].species == FRAGMENT || creature[which].species == MISSILE || (creature[which].species == ORB && creature[which].mode != ARMOUR))
  1454.         {   creature[which].alive = FALSE;
  1455.             change(x, y, EMPTY);
  1456.     }   }
  1457.     elif (c == SKULL)
  1458.     {   if (creature[which].species == ORB)
  1459.         {   effect(FXGETSKULL);
  1460.             orbscore(which, SKULLPOINT);
  1461.         } elif (creature[which].species == FRAGMENT || creature[which].species == DRIP || creature[which].species == MISSILE || creature[which].species == CLOUD)
  1462.         {   effect(FXTHUD);
  1463.             creature[which].alive = FALSE;
  1464.     }   }
  1465.     elif (c == TELEPORT)
  1466.     {   /* Drips, fragments, missiles, orbs, whirlwinds, dogs, clouds
  1467.  */
  1468.         i = whichteleport(x, y);
  1469.         if (blocked(i, creature[which].deltax, creature[which].deltay))
  1470.             creature[which].alive = FALSE;
  1471.         else
  1472.         {   effect(FXUSETELEPORT);
  1473.             creature[which].x = teleport[level][partner(i)].x + creature[which].deltax;
  1474.             creature[which].y = teleport[level][partner(i)].y + creature[which].deltay;
  1475.  
  1476.             if (creature[which].species == ORB)
  1477.             {   orbscore(which, TELPOINT);
  1478.                 creature[which].x = xwrap(creature[which].x);
  1479.                 creature[which].y = ywrap(creature[which].y);
  1480.             } else
  1481.             {   if (!(valid(creature[which].x, creature[which].y)))
  1482.                     creature[which].alive = FALSE;
  1483.                 if (creature[which].species == FRAGMENT)
  1484.                     creature[which].last = SILVER;
  1485.     }   }   }
  1486.     elif (c == ORB)
  1487.     {   i = whichcreature(x, y, ORB, which);
  1488.         if (creature[which].species == DRIP)
  1489.             driporb(x, y, which, i);
  1490.         elif (creature[which].species == FRAGMENT)
  1491.             fragorb(x, y, which, i);
  1492.         elif (creature[which].species == WHIRLWIND)
  1493.             orbwhirlwind(x, y, i, which);
  1494.         elif (creature[which].species == PENGUIN)
  1495.             orbpenguin(x, y, i, which);
  1496.         elif (creature[which].species == MISSILE)
  1497.             orbmissile(x, y, i, which);
  1498.         elif (creature[which].species == DOG)
  1499.             dogorb(x, y, which, i);
  1500.         elif (creature[which].species == ORB)
  1501.             orborb(x, y, which, i);
  1502.         elif (creature[which].species == CLOUD)
  1503.             cloudorb(x, y, which, i);
  1504.     } elif (c == CLOUD)
  1505.     {   i = whichcreature(x, y, CLOUD, which);
  1506.         if (creature[which].species == DRIP)
  1507.             clouddrip(x, y, which, i);
  1508.         elif (creature[which].species == FRAGMENT)
  1509.             cloudfrag(x, y, which, i);
  1510.         elif (creature[which].species == WHIRLWIND)
  1511.             cloudwhirlwind(x, y, which, i);
  1512.         elif (creature[which].species == PENGUIN)
  1513.             cloudpenguin(x, y, which, i);
  1514.         elif (creature[which].species == MISSILE)
  1515.             cloudmissile(x, y, which, i);
  1516.         elif (creature[which].species == DOG)
  1517.             clouddog(x, y, which, i);
  1518.         elif (creature[which].species == ORB)
  1519.             cloudorb(x, y, which, i);
  1520.         elif (creature[which].species == CLOUD)
  1521.             cloudcloud(x, y, which, i);
  1522.     } elif (creature[which].species == ORB)
  1523.     {   if (c <= LASTOBJECT && c != SLAYER && c != BOMB)
  1524.         {   effect(FXGETOBJECT);
  1525.             orbscore(which, object[c].score);
  1526.         }
  1527.         if (c == EMPTY)
  1528.             orbscore(which, EMPTYPOINT);
  1529.         elif (c == SILVER)
  1530.             orbscore(which, SILVERPOINT);
  1531.         elif (c == GOLD)
  1532.             orbscore(which, GOLDPOINT);
  1533.         elif (c == AMMO || c == PULSE || c == SLAYER || c == LIGHTNING)
  1534.         {   if (creature[which].mode != ARMOUR)
  1535.                 creature[which].explode = TRUE;
  1536.             else effect(FXUSEARMOUR);
  1537.         } elif (c == NITRO || c == POWER || c == SLOWER || c == CYCLONE)
  1538.         {   effect(FXGETNITRO);
  1539.             creature[which].speed = speedup(creature[which].speed, TRUE);
  1540.         } elif (c == HEALER || c == LIFE || c == ICE || c == TREASURE || c == UMBRELLA)
  1541.             orbsplit(which);
  1542.         elif (c == BOMB)
  1543.         {   draw(x, y, ORB);
  1544.             bombblast(ORB, which, x, y);
  1545.         } elif (c == ARMOUR)
  1546.         {   creature[which].armour += MODEADD + (rand() % MODERAND);
  1547.             creature[which].mode = ARMOUR;
  1548.         } elif (c == TONGUE)
  1549.         {   creature[which].tongue += MODEADD + (rand() % MODERAND);
  1550.             creature[which].mode = TONGUE;
  1551.         } elif (c == PROTECTOR)
  1552.         {   for (player = 0; player <= 3; player++)
  1553.                 if (worm[player].lives)
  1554.                     for (i = 0; i <= PROTECTORS; i++)
  1555.                         if (protector[player][i].alive)
  1556.                         {   protector[player][i].alive = FALSE;    
  1557.                             if (protector[player][i].visible)
  1558.                                 change(protector[player][i].x, protector[player][i].y, EMPTY);
  1559.         }               }
  1560.         elif (c == MISSILE)
  1561.         {   for (i = 0; i <= CREATURES; i++)
  1562.             {   if (creature[i].alive && creature[i].species == MISSILE)
  1563.                 {   creature[i].alive = FALSE;
  1564.                     change(x, y, EMPTY);
  1565.         }   }   }
  1566.         elif (c == MULTIPLIER)
  1567.         {   creature[which].multi *= 2;
  1568.             if (creature[which].multi > MULTILIMIT)
  1569.                 creature[which].multi = MULTILIMIT;
  1570.         } elif (c == BIAS)
  1571.         {   for (player = 0; player <= 3; player++)
  1572.                 if (worm[player].lives && worm[player].bias)
  1573.                 {   worm[player].bias = 0;
  1574.                     stat(player, BIAS);
  1575.         }       }
  1576.         elif (c == AFFIXER)
  1577.         {   for (player = 0; player <= 3; player++)
  1578.                 if (worm[player].lives)
  1579.                     worm[player].affixer = FALSE;
  1580.         } elif (c == REMNANTS)
  1581.         {   for (player = 0; player <= 3; player++)
  1582.                 if (worm[player].lives)
  1583.                     worm[player].remnants = FALSE;
  1584.         } elif (c == SIDESHOT)
  1585.         {   for (player = 0; player <= 3; player++)
  1586.                 if (worm[player].lives)
  1587.                     worm[player].sideshot = FALSE;
  1588.         } elif (c == MAGNET)
  1589.         {   for (i = 0; i <= MAGNETS; i++)
  1590.                 if (magnet[i].alive)
  1591.                     magnet[i].alive = FALSE;
  1592.         } elif (c == SWITCHER)
  1593.         {   for (xx = 0; xx <= FIELDX; xx++)
  1594.                 for (yy = 0; yy <= FIELDY; yy++)
  1595.                     if (field[xx][yy] >= FIRSTTAIL && field[xx][yy] <= LASTTAIL)
  1596.                         change(xx, yy, WOOD);
  1597.         } elif (c == GROWER)
  1598.         {   effect(FXGETGROWER);
  1599.             for (xx = 0; xx <= FIELDX; xx++)
  1600.                 for (yy = 0; yy <= FIELDY; yy++)
  1601.                     if (field[xx][yy] == WOOD)
  1602.                         for (xxx = xx - 1; xxx <= xx + 1; xxx++)
  1603.                             for (yyy = yy - 1; yyy <= yy + 1; yyy++)                                                                if (valid(xxx, yyy) && field[xxx][yyy] == EMPTY)
  1604.                                 field[xxx][yyy] = TEMPWOOD;
  1605.             for (xx = 0; xx <= FIELDX; xx++)
  1606.                 for (yy = 0; yy <= FIELDY; yy++)
  1607.                     if (field[xx][yy] == TEMPWOOD)
  1608.                         change(xx, yy, WOOD);
  1609.         } elif (c == CLOCK)
  1610.             secondsperlevel -= rand() % CLOCKRAND;
  1611. }   }
  1612.  
  1613. x = creature[which].x; /* We refresh these in case a fragment has been */
  1614. y = creature[which].y; /* reflected. Yes, it is vital. */
  1615.  
  1616. if (creature[which].alive && creature[which].visible && (creature[which].deltax || creature[which].deltay))
  1617. {   if (creature[which].species == MISSILE)
  1618.         change(x, y, FIRSTMISSILE + creature[which].type);
  1619.     elif (creature[which].species == DRIP)
  1620.         change(x, y, FIRSTDRIP + creature[which].type);
  1621.     elif (creature[which].species == ORB)
  1622.     {   field[x][y] = ORB;
  1623.         if (creature[which].mode == TONGUE)
  1624.             draw(x, y, ORBTONGUE);
  1625.         elif (creature[which].mode == ARMOUR)
  1626.             draw(x, y, ORBARMOUR);
  1627.         else draw(x, y, ORB);
  1628.     } else /* fragments, goats, penguins, cyclones, dogs, clouds */
  1629.     change(x, y, creature[which].species);
  1630. }
  1631.  
  1632. if (creature[which].alive)
  1633. {   /* decide whether to fire */
  1634.     if (creature[which].species == GOAT)
  1635.     {   if (!(rand() % 10))
  1636.         {   for (i = 0; i <= CREATURES; i++)
  1637.             {   if (!creature[i].alive)
  1638.                 {   creature[i].deltax = (rand() % 3) - 1;
  1639.                     creature[i].deltay = (rand() % 3) - 1;
  1640.                     if
  1641.                     (   valid(x + creature[i].deltax, y + creature[i].deltay)
  1642.                     &&  (creature[i].deltax || creature[i].deltay)
  1643.                     )
  1644.                     {   c = field[x + creature[i].deltax][y + creature[i].deltay];
  1645.                         if
  1646.                         (   (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1647.                         ||  (c >= FIRSTTAIL && c <= LASTTAIL)
  1648.                         )
  1649.                         {   effect(FXGOATFIRE);
  1650.                             creature[i].alive = TRUE;
  1651.                             creature[i].species = FRAGMENT;
  1652.                             creature[i].x = x + creature[i].deltax;
  1653.                             creature[i].y = y + creature[i].deltay;
  1654.                             creature[i].visible = TRUE;
  1655.                             creature[i].last = EMPTY;
  1656.                             creature[i].speed = (SBYTE) atleast(FRAGSPEED - (level / 2), 1);
  1657.                     }   }
  1658.                     break;
  1659.     }   }   }   }
  1660.     elif (creature[which].species == CLOUD)
  1661.     {   if (!(rand() % 30))
  1662.         {   cloudbullet(which, x, y, -1);
  1663.             cloudbullet(which, x, y, 1);
  1664. }   }   }
  1665. }
  1666.  
  1667. MODULE void cloudbullet(UBYTE which, SBYTE x, SBYTE y, SBYTE deltay)
  1668. {   UBYTE i, c;
  1669.  
  1670.     for (i = 0; i <= CREATURES; i++)
  1671.     {   if (!creature[i].alive)
  1672.         {   creature[i].deltax = 0;
  1673.             creature[i].deltay = deltay;
  1674.             if (valid(x + creature[i].deltax, y + creature[i].deltay))
  1675.             {   c = field[x + creature[i].deltax][y + creature[i].deltay];
  1676.                 if
  1677.                 (   (c >= FIRSTEMPTY && c <= LASTEMPTY)
  1678.                 ||  (c >= FIRSTTAIL && c <= LASTTAIL)
  1679.                 )
  1680.                 {   effect(FXGOATFIRE); /* this is used for clouds too */
  1681.                     creature[i].alive = TRUE;
  1682.                     creature[i].species = FRAGMENT;
  1683.                     creature[i].x = x;
  1684.                     creature[i].y = y + creature[i].deltay;
  1685.                     creature[i].visible = TRUE;
  1686.                     creature[i].last = EMPTY;
  1687.                     creature[i].speed = (SBYTE) atleast(FRAGSPEED - (level / 2), 1);
  1688.             }   }
  1689.             break;
  1690. }   }   }
  1691.  
  1692. MODULE void orbsplit(SBYTE which)
  1693. {   SBYTE   copy = 0, i;
  1694.  
  1695.     effect(FXORBSPLIT);
  1696.     for (i = 0; i <= CREATURES; i++)
  1697.     {   if (!creature[i].alive)
  1698.         {   creature[i].x       = creature[which].x;
  1699.             creature[i].y       = creature[which].y;
  1700.             creature[i].score   = creature[which].score;
  1701.             creature[i].armour  = creature[which].armour;
  1702.             creature[i].tongue  = creature[which].tongue;
  1703.             creature[i].mode    = creature[which].mode;
  1704.             creature[i].speed   = creature[which].speed;
  1705.             creature[i].explode = FALSE;
  1706.             creature[i].multi   = creature[which].multi;
  1707.             creature[i].last    = EMPTY;
  1708.             switch (copy)
  1709.             {
  1710.             case 0:
  1711.                 if (creature[which].deltax != -1 || creature[which].deltay != -1)
  1712.                 {   creature[i].deltax = -1;
  1713.                     creature[i].deltay = -1;
  1714.                     creature[i].alive = TRUE;
  1715.                 }
  1716.             break;
  1717.             case 1:
  1718.                 if (creature[which].deltax != 1 || creature[which].deltay != 1)
  1719.                 {   creature[i].deltax = 1;
  1720.                     creature[i].deltay = 1;
  1721.                     creature[i].alive = TRUE;
  1722.                 }
  1723.             break;
  1724.             case 2:
  1725.                 if (creature[which].deltax != 1 || creature[which].deltay != -1)
  1726.                 {   creature[i].deltax = 1;
  1727.                     creature[i].deltay = -1;
  1728.                     creature[i].alive = TRUE;
  1729.                 }
  1730.             break;
  1731.             case 3:
  1732.                 if (creature[which].deltax != -1 || creature[which].deltay != 1)
  1733.                 {   creature[i].deltax = -1;
  1734.                     creature[i].deltay = 1;
  1735.                     creature[i].alive = TRUE;
  1736.                 }
  1737.             break;
  1738.             default:
  1739.             break;
  1740.             }
  1741.             if (++copy >= 4)
  1742.                 return;
  1743. }    }    }
  1744.  
  1745. MODULE void orientworms(void)
  1746. {   SBYTE player;
  1747.  
  1748.     for (player = 0; player <= 3; player++)
  1749.     {    worm[player].speed = NORMAL;
  1750.         if (worm[player].lives)
  1751.             stat(player, NITRO);
  1752.         worm[player].moved = FALSE;
  1753.         worm[player].x = startx[level];
  1754.         worm[player].y = starty[level];
  1755.         switch (player)
  1756.         {
  1757.         case 0:
  1758.             worm[0].deltax = -1;
  1759.             worm[0].deltay = 0;
  1760.             break;
  1761.         case 1:
  1762.             worm[1].deltax = 1;
  1763.             worm[1].deltay = 0;
  1764.             break;
  1765.         case 2:
  1766.             worm[2].deltax = 0;
  1767.             worm[2].deltay = -1;
  1768.             break;
  1769.         case 3:
  1770.             worm[3].deltax = 0;
  1771.             worm[3].deltay = 1;
  1772.             break;
  1773.         default:
  1774.             break;
  1775. }   }   }
  1776.  
  1777. SBYTE partner(SBYTE which)
  1778. {   if (which % 2 == 0)
  1779.         return((SBYTE) (which + 1));
  1780.     else return((SBYTE) (which - 1));
  1781. }
  1782.  
  1783. /* NAME        putletter -- Put a letter onto the field
  1784. SYNOPSIS    void putletter(SBYTE player);
  1785. INPUTS        SBYTE player -
  1786.             0-3: player on whose behalf the letter is put on for
  1787.             -1: any letter
  1788. RESULT        none */
  1789.  
  1790. MODULE void putletter(SBYTE player)
  1791. {   ABOOL done;
  1792.     SBYTE i, x, y;
  1793.     UBYTE letter;
  1794.  
  1795.     do
  1796.     {   done = findempty(&x, &y, FIRSTEMPTY, LASTEMPTY);
  1797.     } while (!done);
  1798.     if (player != -1)
  1799.     {   for (i = 0; i <= LETTERS; i++)
  1800.             if (!(letters[player][i]))
  1801.             {   break;
  1802.             }
  1803.         if (i > LETTERS) /* if no spare letters */
  1804.             letter = rand() % (LETTERS + 1);
  1805.         else
  1806.         {   do
  1807.                 letter = rand() % (LETTERS + 1);
  1808.             while (letters[player][letter]);
  1809.     }   }
  1810.     else letter = rand() % (LETTERS + 1);
  1811.     change(x, y, letter + FIRSTLETTER);
  1812.     letterx = x;
  1813.     lettery = y;
  1814.     lettertype = letter + FIRSTLETTER;
  1815. }
  1816.  
  1817. /* NAME     queue -- adds a keystroke to the key queue
  1818. SYNOPSIS    name(SBYTE, SBYTE, SBYTE);
  1819. FUNCTION    Adds a keystroke to the in-game key queue.
  1820. INPUTS      player - player that pressed the key
  1821.             deltax - the deltax of the key
  1822.             deltay - the deltay of the key
  1823. IMPLEMENTATION
  1824.             thewormqueue[] array has WORMQUEUELIMIT as its last index.
  1825.             It is implemented as a FIFO stack rather than LIFO so that
  1826.             the keystrokes are processed in the correct order (that is,
  1827.             the order in which they were pressed). The oldest keystroke
  1828.             is always at index [0], the next oldest at [1], and so on
  1829.             upwards to the newest keystroke, at [worm[player].pos].
  1830.             Keystrokes are removed from the bottom of the array ([0]),
  1831.             and the rest of the array is shuffled down to fill the gap,
  1832.             so that the contents of [1] go to [0], the contents of [2]
  1833.             go to [1], etc. worm[player].pos is adjusted to always point
  1834.             to the newest entry, which is the 'end' of the queue.
  1835. MODULE      engine.c */
  1836.  
  1837. AGLOBAL void wormqueue(SBYTE player, SBYTE deltax, SBYTE deltay)
  1838. {       if (worm[player].pos < WORMQUEUELIMIT)
  1839.     {    worm[player].pos++;
  1840.         thewormqueue[player][worm[player].pos].deltax = deltax;
  1841.         thewormqueue[player][worm[player].pos].deltay = deltay;
  1842. }    }
  1843.  
  1844. MODULE void dogqueue(SBYTE which, SBYTE deltax, SBYTE deltay)
  1845. {       if (creature[which].pos < DOGQUEUELIMIT)
  1846.         {       creature[which].pos++;
  1847.                 thedogqueue[which][creature[which].pos].deltax = deltax;
  1848.                 thedogqueue[which][creature[which].pos].deltay = deltay;
  1849. }       }
  1850.  
  1851. MODULE void reflect(UBYTE which)
  1852. {   creature[which].deltax  = -creature[which].deltax;
  1853.     creature[which].deltay  = -creature[which].deltay;
  1854.     creature[which].x      +=  creature[which].deltax * 2;
  1855.     creature[which].y      +=  creature[which].deltay * 2;
  1856. }
  1857.  
  1858. ABOOL savefields(STRPTR fieldname)
  1859. {    SBYTE    i, j;
  1860.     TEXT    IOBuffer[NAMELENGTH + 1];
  1861.  
  1862.     matchteleports();
  1863.  
  1864.     if (!ZOpen(fieldname, TRUE))
  1865.         return FALSE;
  1866.  
  1867.     /* write header
  1868.  */
  1869.  
  1870.     strcpy(IOBuffer,                    "FSET 5.5");
  1871.     IOBuffer[9]                            = levels;
  1872.     if (!ZWrite(IOBuffer, 10))
  1873.     {   ZClose();
  1874.         return FALSE;
  1875.     }
  1876.  
  1877.     /* write high score table
  1878.  */
  1879.  
  1880.     for (i = 0; i <= HISCORES; i++)
  1881.     {    IOBuffer[0]                        =  hiscore[i].player;
  1882.         IOBuffer[1]                        =  hiscore[i].level;
  1883.         IOBuffer[2]                        =  0;
  1884.         IOBuffer[3]                        =  hiscore[i].score / 65536;
  1885.         IOBuffer[4]                        = (hiscore[i].score % 65536) / 256;
  1886.         IOBuffer[5]                        = (hiscore[i].score % 65536) % 256;
  1887.         if (!ZWrite(IOBuffer, 6))
  1888.         {   ZClose();
  1889.             return FALSE;
  1890.         }
  1891.  
  1892.         for (j = 0; j <= NAMELENGTH; j++)
  1893.             IOBuffer[j]                        = hiscore[i].name[j];
  1894.         if (!ZWrite(IOBuffer, NAMELENGTH + 1))
  1895.         {   ZClose();
  1896.             return FALSE;
  1897.         }
  1898.         for (j = 0; j <= TIMELENGTH; j++)
  1899.             IOBuffer[j]                        = hiscore[i].time[j];
  1900.         if (!ZWrite(IOBuffer, TIMELENGTH + 1))
  1901.         {   ZClose();
  1902.             return FALSE;
  1903.         }
  1904.         for (j = 0; j <= DATELENGTH; j++)
  1905.             IOBuffer[j]                        = hiscore[i].date[j];
  1906.         if (!ZWrite(IOBuffer, DATELENGTH + 1))
  1907.         {   ZClose();
  1908.             return FALSE;
  1909.     }    }
  1910.  
  1911.     /* write level data
  1912.  */
  1913.  
  1914.     for (i = 0; i <= levels; i++)
  1915.     {   IOBuffer[0]                        = startx[i];
  1916.         IOBuffer[1]                        = starty[i];
  1917.         IOBuffer[2]                        = teleport[i][0].alive;
  1918.         IOBuffer[3]                        = teleport[i][0].x;
  1919.         IOBuffer[4]                        = teleport[i][0].y;
  1920.         IOBuffer[5]                        = teleport[i][1].alive;
  1921.         IOBuffer[6]                        = teleport[i][1].x;
  1922.         IOBuffer[7]                        = teleport[i][1].y;
  1923.         if (!ZWrite(IOBuffer, 8))
  1924.         {   ZClose();
  1925.             return FALSE;
  1926.         }
  1927.  
  1928.         if (!ZWrite((char *) &board[i][0][0], (FIELDX + 1) * (FIELDY + 1)))
  1929.         {   ZClose();
  1930.             return FALSE;
  1931.     }    }
  1932.  
  1933.     /* write version string
  1934.  */
  1935.  
  1936.     if (!ZWrite(VERSION, strlen(VERSION)))
  1937.     {   ZClose();
  1938.         return FALSE;
  1939.     }
  1940.  
  1941.     ZClose();
  1942.  
  1943.     if (clearthem)
  1944.         clearhiscores();
  1945.     modified = FALSE;
  1946.     return TRUE;
  1947. }
  1948.  
  1949. void saylevel(COLOUR colour)
  1950. {    TEXT mainstring[15] = "Level ", tempstring[4];
  1951.  
  1952.     if (level > 0)
  1953.     {    stci_d(&mainstring[6], level);
  1954.         strcat((char*) mainstring, " of ");
  1955.         stci_d(tempstring, levels);
  1956.         strcat((char*) mainstring, (char*) tempstring);
  1957.         say(mainstring, colour);
  1958.     } else
  1959.     {    if (a == FIELDEDIT)
  1960.             say("Bonus Level", colour);
  1961.         else
  1962.         {    if (leveltype == TREASURE)
  1963.                             say("Bonus Level: Treasury!", colour);
  1964.                         elif (leveltype == DRIP)
  1965.                             say("Bonus Level: Drips!", colour);
  1966.                         else
  1967.                         {   /* assert(leveltype == CLOUD);
  1968.  */
  1969.                             say("Bonus Level: Clouds!", colour);
  1970. }       }       }       }
  1971.  
  1972. MODULE SBYTE slowdown(SBYTE speed)
  1973. {    speed *= 2;
  1974.     if (speed > SLOW)
  1975.         speed = SLOW;
  1976.     return(speed);
  1977. }
  1978.  
  1979. MODULE void slowloop(void)
  1980. {   SBYTE i, player, which, x, xx, y, yy;
  1981.     UBYTE thissy;
  1982.  
  1983.     /* decrement worm strength */
  1984.  
  1985.     for (player = 0; player <= 3; player++)
  1986.         if (worm[player].lives > 0 && ice == -1 || ice == player)
  1987.         {   if (worm[player].bias > 0)
  1988.             {   worm[player].bias--;
  1989.                 stat(player, BIAS);
  1990.             }
  1991.             if (worm[player].ice > 0 && --worm[player].ice == 0)
  1992.             {   for (which = 0; which <= 3; which++)
  1993.                     if (player != which)
  1994.                         worm[player].pos = -1;
  1995.                 ice = -1;
  1996.             }
  1997.             if (worm[player].mode == ARMOUR)
  1998.             {   if (--worm[player].armour == 0)
  1999.                 {   if (worm[player].tongue > 0)
  2000.                         worm[player].mode = TONGUE;
  2001.                     else worm[player].mode = NULL;
  2002.                 }
  2003.                 stat(player, ARMOUR);
  2004.             } elif (worm[player].mode == TONGUE)
  2005.             {   if (--worm[player].tongue == 0)
  2006.                 {   if (worm[player].armour > 0)
  2007.                         worm[player].mode = ARMOUR;
  2008.                     else worm[player].mode = NULL;
  2009.                 }
  2010.                 stat(player, TONGUE);
  2011.         }   }
  2012.  
  2013.     /* blank out old causes */
  2014.  
  2015.     for (player = 0; player <= 3; player++)
  2016.     {   if (worm[player].lives > 0 && r > worm[player].causewait)
  2017.         {   drawcause(player, BLACK);
  2018.             worm[player].causewait = (ULONG) -1; /* most future time possible */
  2019.     }   }
  2020.  
  2021.     if (level)
  2022.     {    /* decrement orb strength */
  2023.         for (which = 0; which <= CREATURES; which++)
  2024.             if (creature[which].alive && creature[which].species == ORB)
  2025.                 if (creature[which].mode == ARMOUR)
  2026.                 {   if (--creature[which].armour == 0)
  2027.                         if (creature[which].tongue > 0)
  2028.                             creature[which].mode = TONGUE;
  2029.                         else creature[which].mode = NULL;
  2030.                 } elif (creature[which].mode == TONGUE)
  2031.                 {   if (--creature[which].tongue == 0)
  2032.                         if (creature[which].armour > 0)
  2033.                             creature[which].mode = ARMOUR;
  2034.                         else creature[which].mode = NULL;
  2035.                 }
  2036.  
  2037.         /* create goats */
  2038.         if
  2039.         (   (!(rand() % freq))
  2040.         &&  findempty(&x, &y, FIRSTGOAT, LASTGOAT)
  2041.         &&  field[x][y] != GOAT
  2042.         )
  2043.         {   for (i = 0; i <= CREATURES; i++)
  2044.             {   if (!creature[i].alive)
  2045.                 {   effect(FXGOATBORN);
  2046.                     creature[i].x = x;
  2047.                     creature[i].y = y;
  2048.                     creature[i].alive = TRUE;
  2049.                     creature[i].species = GOAT;
  2050.                     creature[i].last = creature[i].oldlast = field[x][y];
  2051.                     creature[i].speed = (SBYTE) atleast(GOATSPEED - (level / 2), 2);
  2052.                     creature[i].visible = TRUE;
  2053.                     change(x, y, GOAT);
  2054.                     break;
  2055.         }   }   }
  2056.  
  2057.         /* create orbs */
  2058.         if
  2059.         (   (!(rand() % freq))
  2060.          && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY)
  2061.         )
  2062.         {   for (i = 0; i <= CREATURES; i++)
  2063.             {   if (!creature[i].alive)
  2064.                 {   effect(FXORBBORN);
  2065.                     creature[i].deltax = (rand() % 2) * 2 - 1;
  2066.                     creature[i].deltay = (rand() % 2) * 2 - 1;
  2067.                     creature[i].score = 0;
  2068.                     creature[i].alive = TRUE;
  2069.                     creature[i].armour = 0;
  2070.                     creature[i].tongue = 0;
  2071.                     creature[i].mode = NULL;
  2072.                     creature[i].speed = (SBYTE) atleast(ORBSPEED - (level / 2), 2);
  2073.                     creature[i].species = ORB;
  2074.                     creature[i].explode = FALSE;
  2075.                     creature[i].multi = 1;
  2076.                     creature[i].x = x;
  2077.                     creature[i].y = y;
  2078.                     creature[i].last = EMPTY;
  2079.                     creature[i].visible = TRUE;
  2080.                     change(x, y, ORB);
  2081.                     break;
  2082.         }   }   }
  2083.  
  2084.         /* create penguins */
  2085.         if
  2086.         (   (!(rand() % freq))
  2087.          && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2088.         {   for (i = 0; i <= CREATURES; i++)
  2089.                 if (!(creature[i].alive))
  2090.                 {   effect(FXPENGUINBORN);
  2091.                     creature[i].x = x;
  2092.                     creature[i].y = y;
  2093.                     creature[i].last = EMPTY;
  2094.                     creature[i].speed = (SBYTE) atleast(PENGUINSPEED - (level / 2), 2);
  2095.                     creature[i].visible = TRUE;
  2096.                     creature[i].deltax = 0;
  2097.                     creature[i].deltay = 0;
  2098.                     creature[i].species = PENGUIN;
  2099.                     creature[i].alive = TRUE;
  2100.                     change(x, y, PENGUIN);
  2101.                     break;
  2102.         }       }
  2103.  
  2104.         /* create dogs */
  2105.         if ((!(rand() % freq)) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2106.         {   for (i = 0; i <= CREATURES; i++)
  2107.                 if (!(creature[i].alive))
  2108.                 {   creature[i].x = x;
  2109.                     creature[i].y = y;
  2110.                     creature[i].last = EMPTY;
  2111.                     creature[i].speed = (SBYTE) atleast(DOGSPEED - (level / 2), 2);
  2112.                     creature[i].visible = TRUE;
  2113.                     creature[i].deltax = 0;
  2114.                     creature[i].deltay = 0;
  2115.                     creature[i].species = DOG;
  2116.                     creature[i].alive = TRUE;
  2117.                     creature[i].pos = -1;
  2118.                     creature[i].dormant = DORMANT; /* dormant */
  2119.                     field[x][y] = DOG;
  2120.                     draw(x, y, DOGDORMANT);
  2121.                     break;
  2122.         }       }
  2123.  
  2124.         /* create slime */
  2125.         if ((!(rand() % (freq * 2))) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2126.             change(x, y, SLIME);
  2127.  
  2128.         /* grow slime */
  2129.         if (!(rand() % (freq * 2)))
  2130.         {   for (x = 0; x <= FIELDX; x++)
  2131.                 for (y = 0; y <= FIELDY; y++)
  2132.                     if (field[x][y] == SLIME)
  2133.                         for (xx = x - 1; xx <= x + 1; xx++)
  2134.                             for (yy = y - 1; yy <= y + 1; yy++)
  2135.                                 if (valid(xx, yy) && field[xx][yy] == EMPTY && !(rand() % 2))
  2136.                                     field[xx][yy] = TEMPSLIME;
  2137.             for (x = 0; x <= FIELDX; x++)
  2138.                 for (y = 0; y <= FIELDY; y++)
  2139.                     if (field[x][y] == TEMPSLIME)
  2140.                         change(x, y, SLIME);
  2141.         }
  2142.                
  2143.         /* create timebombs
  2144.  */
  2145.         if ((!(rand() % (freq * 8))) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2146.         {   for (i = 0; i <= CREATURES; i++)
  2147.             if (!(creature[i].alive))
  2148.             {   creature[i].x = x;
  2149.                 creature[i].y = y;
  2150.                 creature[i].last = EMPTY;
  2151.                 creature[i].speed = (SBYTE) atleast(TIMEBOMBSPEED - (level / 2), 2);
  2152.                 creature[i].visible = TRUE;
  2153.                 creature[i].deltax = 0;
  2154.                 creature[i].deltay = 0;
  2155.                 creature[i].species = TIMEBOMB;
  2156.                 creature[i].alive = TRUE;
  2157.                 creature[i].time = 10;
  2158.                 field[x][y] = TIMEBOMB;
  2159.                 draw(x, y, ZERO + 9);
  2160.                 break;
  2161.     }   }   }
  2162.  
  2163.     /* create drips */
  2164.     if
  2165.     (   (level && (!(rand() % freq)))
  2166.      || ((!level) && leveltype == DRIP && (!(rand() % FREQ_DRIP)))
  2167.     )
  2168.     {   x = (rand() % (FIELDX + 1));
  2169.         y = (rand() % 3);
  2170.         thissy = field[x][y];
  2171.         if (thissy >= FIRSTEMPTY && thissy <= LASTEMPTY)
  2172.         {   for (i = 0; i <= CREATURES; i++)
  2173.             {   if (!creature[i].alive)
  2174.                 {   effect(FXDRIPBORN);
  2175.                     creature[i].alive      = TRUE;
  2176.                     creature[i].last       = EMPTY;
  2177.                     creature[i].species    = DRIP;
  2178.                     creature[i].type       = rand() % 4;
  2179.                     creature[i].x          = x;
  2180.                     creature[i].y          = y;
  2181.                     creature[i].deltax     = 0;
  2182.                     creature[i].deltay     = 1;
  2183.                     creature[i].visible    = TRUE;
  2184.                     if (level)
  2185.                         creature[i].speed  = (SBYTE) atleast(DRIPSPEED - (level / 2), 2);
  2186.                     else creature[i].speed = BONUSDRIPSPEED;
  2187.                     change(x, y, FIRSTDRIP + creature[which].type);
  2188.                     break;
  2189.     }   }   }   }
  2190.  
  2191.     /* create clouds */
  2192.     if
  2193.     (   (level && (!(rand() % freq)))
  2194.      || ((!level) && leveltype == CLOUD && (!(rand() % FREQ_CLOUD)))
  2195.     )
  2196.     {   x = (rand() % (FIELDX - 1)) + 1;
  2197.         y = (rand() % (FIELDY - 1)) + 1;
  2198.         /* If you create clouds at an extreme horizontal position
  2199.         (0 or FIELDX), will cause a crash because the deltas will be
  2200.         wrong. */
  2201.         thissy = field[x][y];
  2202.         if (thissy >= FIRSTEMPTY && thissy <= LASTEMPTY)
  2203.         {   for (i = 0; i <= CREATURES; i++)
  2204.             {   if (!creature[i].alive)
  2205.                 {   creature[i].alive       = TRUE;
  2206.                     creature[i].last        = EMPTY;
  2207.                     creature[i].species     = CLOUD;
  2208.                     creature[i].x           = x;
  2209.                     creature[i].y           = y;
  2210.                     if (x < FIELDX / 2)
  2211.                         creature[i].deltax  = 1;
  2212.                     else creature[i].deltax = -1;
  2213.                     creature[i].deltay      = 0;
  2214.                     creature[i].visible     = TRUE;
  2215.                     if (level)
  2216.                         creature[i].speed   = (SBYTE) atleast(CLOUDSPEED - (level / 2), 3);
  2217.                     else creature[i].speed  = BONUSCLOUDSPEED;
  2218.                     change(x, y, CLOUD);
  2219.                     break;
  2220.     }   }   }   }
  2221.  
  2222.     /* create objects
  2223.  */
  2224.     for (which = 0; which <= LASTOBJECT; which++)
  2225.         if (level || leveltype != TREASURE || which == TREASURE)
  2226.         {   if (!(rand() % object[which].freq) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2227.                 change(x, y, which);
  2228.         } elif (!(rand() % (object[which].freq / 10)) && findempty(&x, &y, FIRSTEMPTY, LASTEMPTY))
  2229.             change(x, y, which);
  2230.  
  2231.     /* create teleports
  2232.  */
  2233.     if (!(rand() % FREQ_TELEPORT)
  2234.     && !teleport[level][2].alive
  2235.     && findempty(&(teleport[level][2].x), &(teleport[level][2].y), FIRSTEMPTY, LASTEMPTY)
  2236.     && findempty(&(teleport[level][3].x), &(teleport[level][3].y), FIRSTEMPTY, LASTEMPTY)
  2237.     && (teleport[level][2].x != teleport[level][3].x || teleport[level][2].y != teleport[level][3].y))
  2238.     {   teleport[level][2].alive = TRUE;
  2239.         teleport[level][3].alive = TRUE;
  2240.         change(teleport[level][2].x, teleport[level][2].y, TELEPORT);
  2241.         change(teleport[level][3].x, teleport[level][3].y, TELEPORT);
  2242. }   }
  2243.  
  2244. MODULE SBYTE speedup(SBYTE speed, ABOOL nitro)
  2245. {    speed /= 2;
  2246.     if (speed < FAST)
  2247.         speed = FAST;
  2248.     return(speed);
  2249. }
  2250.  
  2251. MODULE ULONG squareblast(SBYTE type, SBYTE player, SBYTE thissy, SBYTE x, SBYTE y)
  2252. {   SBYTE which;
  2253.     ULONG score = 0;
  2254.     SBYTE filler;
  2255.  
  2256.     if (type == HEAD && worm[player].bias)
  2257.         filler = SILVER;
  2258.     else filler = EMPTY;
  2259.  
  2260.     if (thissy <= LASTOBJECT)
  2261.         change(x, y, filler);
  2262.     elif (thissy >= FIRSTTAIL && thissy <= LASTTAIL)
  2263.         change(x, y, filler);
  2264.     elif (thissy == ORB)
  2265.     {   which = whichcreature(x, y, ORB, 255);
  2266.         if (creature[which].mode != ARMOUR)
  2267.         {   effect(FXORBDEATH);
  2268.             creature[which].alive = FALSE;
  2269.             score = creature[which].score;
  2270.             if (type == HEAD && worm[player].bias)
  2271.                 worm[player].lives += ORBBLOOD;
  2272.             change(x, y, BONUS);
  2273.         } else effect(FXUSEARMOUR);
  2274.     } elif (thissy >= FIRSTDRIP && thissy <= LASTDRIP)
  2275.     {   creature[whichcreature(x, y, DRIP, 255)].alive = FALSE;
  2276.         change(x, y, filler);
  2277.     } elif (thissy >= FIRSTHEAD && thissy <= LASTHEAD)
  2278.     {   if (type != HEAD || player != thissy - FIRSTHEAD)
  2279.             if (worm[thissy - FIRSTHEAD].mode != ARMOUR)
  2280.             {   worm[thissy - FIRSTHEAD].cause = BOMB;
  2281.                 worm[thissy - FIRSTHEAD].alive = FALSE;
  2282.                 stat(thissy - FIRSTHEAD, LIFE);
  2283.                 if (type == HEAD)
  2284.                     worm[thissy - FIRSTHEAD].victor = player;
  2285.                 else
  2286.                 {   worm[thissy - FIRSTHEAD].victor = -1;
  2287.                     score = KILLWORM; // worms will get this bonus from death(), so it is not given for them here.
  2288.             }   }
  2289.             else effect(FXUSEARMOUR);
  2290.     } elif (thissy >= FIRSTMISSILE && thissy <= LASTMISSILE)
  2291.     {   if (type != HEAD || player != thissy - FIRSTMISSILE)
  2292.         {   creature[whichcreature(x, y, MISSILE, 255)].alive = FALSE;
  2293.             change(x, y, filler);
  2294.     }    }
  2295.     elif (thissy == PENGUIN)
  2296.     {    creature[whichcreature(x, y, PENGUIN, 255)].alive = FALSE;
  2297.         change(x, y, filler);
  2298.     } elif (thissy == FRAGMENT)
  2299.     {    creature[whichcreature(x, y, FRAGMENT, 255)].alive = FALSE;
  2300.         change(x, y, filler);
  2301.     } elif (thissy == GOAT)
  2302.     {   creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  2303.         change(x, y, BONUS);
  2304.     }
  2305.     return(score);
  2306. }
  2307.  
  2308. void timeloop(void)
  2309. {           TEXT  timedisplay[5] = {"#:##"};
  2310.     PERSIST ABOOL outoftime      = FALSE;
  2311.             UBYTE i;
  2312.  
  2313.     secondsleft = atleast(secondsleft, 0);
  2314.     timedisplay[0] = 48 +  (secondsleft / 60);
  2315.     timedisplay[2] = 48 + ((secondsleft % 60) / 10);
  2316.     timedisplay[3] = 48 + ((secondsleft % 60) % 10);
  2317.  
  2318.     if (!level)
  2319.     {    say(timedisplay, worm[treasurer].colour);
  2320.         if (!secondsleft)
  2321.         {    level = reallevel + 1;
  2322.             secondsleft = SECONDSPERLEVEL;
  2323.             newlevel(treasurer);
  2324.     }    }
  2325.     elif (!secondsleft)
  2326.         {   if (!outoftime)
  2327.             {   effect(FXTIMEALERT);
  2328.                 say("Out of time!", WHITE);
  2329.                 outoftime = TRUE;
  2330.                 freq /= 2;
  2331.                 for (i = 0; i <= CREATURES; i++)
  2332.                     if (creature[i].alive)
  2333.                         creature[i].speed = speedup(creature[i].speed, TRUE);
  2334.         }   }
  2335.     else
  2336.     {    outoftime = FALSE;
  2337.         say(timedisplay, WHITE);
  2338. }    }
  2339.  
  2340. void train(SCANCODE scancode)
  2341. {    SBYTE i, x, y;
  2342.     UBYTE thissy;
  2343.  
  2344.     switch(scancode) {
  2345.     case HELP:
  2346.         trainer = !trainer;
  2347.     break;
  2348.     case NUMERICSLASH:
  2349.         /* Complete the level.
  2350.  */
  2351.         if (trainer)
  2352.         {    trainer = FALSE;
  2353.             if (worm[1].lives > 0)
  2354.                 for (i = 0; i <= LETTERS; i++)
  2355.                 {   letters[1][i] = TRUE;
  2356.                     drawletter(1, FIRSTLETTER + i, NORMAL);
  2357.         }       }
  2358.     break;
  2359.     case NUMERICASTERISK:
  2360.         /* Change most squares to gold.
  2361.  */
  2362.         if (trainer)
  2363.         {    trainer = FALSE;
  2364.             for (x = 0; x <= FIELDX; x++)
  2365.                 for (y = 0; y <= FIELDY; y++)
  2366.                     if (field[x][y] == FIRSTTAIL + 1)
  2367.                         change(x, y, METAL);
  2368.                     else
  2369.                     {   thissy = field[x][y];
  2370.                         if
  2371.                         (   thissy != STONE
  2372.                         &&  thissy != GOAT
  2373.                         &&  thissy != ORB
  2374.                         &&  thissy != SKULL
  2375.                         && (thissy < FIRSTHEAD || thissy > LASTHEAD)
  2376.                         && (thissy < FIRSTLETTER || thissy > LASTLETTER)
  2377.                         )
  2378.                             change(x, y, GOLD);
  2379.         }           }
  2380.     break;
  2381.     case NUMERICPLUS:
  2382.         /* Full lives, tongue, bias, ammo, power, nitro, affixer
  2383.         and remnants. */
  2384.         if (trainer)
  2385.         {    trainer = FALSE;
  2386.             if (worm[1].lives > 0)
  2387.             {    worm[1].lives = LIVESLIMIT;
  2388.                 stat(1, LIFE);
  2389.                 worm[1].tongue = MODELIMIT;
  2390.                 worm[1].mode = TONGUE;
  2391.                 stat(1, TONGUE);
  2392.                 worm[1].bias = BIASLIMIT;
  2393.                 stat(1, BIAS);
  2394.                 worm[1].ammo = AMMOLIMIT;
  2395.                 stat(1, AMMO);
  2396.                 worm[1].power = POWERLIMIT;
  2397.                 stat(1, POWER);
  2398.                 worm[1].nitro = TRUE;
  2399.                 stat(1, NITRO);
  2400.                                 worm[1].affixer = TRUE;
  2401.                 worm[1].remnants = TRUE;
  2402.                                 worm[1].sideshot = TRUE;
  2403.                 trainer = FALSE;
  2404.         }    }
  2405.     break;
  2406.     default:
  2407.     break;
  2408. }    }
  2409.  
  2410. MODULE void turnworm(SBYTE player, SBYTE deltax, SBYTE deltay)
  2411. {
  2412. if (worm[player].nitro || !deltax || !deltay)
  2413. {    if (worm[player].deltax == deltax && worm[player].deltay == deltay)
  2414.     {    worm[player].speed = speedup(worm[player].speed, worm[player].nitro);
  2415.         stat(player, NITRO);
  2416.     } elif (worm[player].deltax == -deltax && worm[player].deltay == -deltay)
  2417.     {    worm[player].speed = slowdown(worm[player].speed);
  2418.         stat(player, NITRO);
  2419.     } else
  2420.     {    worm[player].deltax = deltax;
  2421.         worm[player].deltay = deltay;
  2422. }    }
  2423. }
  2424.  
  2425. AGLOBAL void updatesquare(SBYTE x, SBYTE y)
  2426. {    SBYTE    which;
  2427.  
  2428.     if (startx[level] == x && starty[level] == y)
  2429.         draw(x, y, START);
  2430.     elif (board[level][x][y] == TELEPORT)
  2431.     {    for (which = 0; which <= 1; which++)
  2432.             if (teleport[level][which].alive && teleport[level][which].x == x && teleport[level][which].y == y)
  2433.                 draw(x, y, ONE + which);
  2434.     } else draw(x, y, board[level][x][y]);
  2435. }
  2436.  
  2437. SBYTE valid(SBYTE x, SBYTE y)
  2438. {    if (x >= 0 && x <= FIELDX && y >= 0 && y <= FIELDY)
  2439.         return(TRUE);
  2440.     else
  2441.         return(FALSE);
  2442. }
  2443.  
  2444. MODULE UBYTE whichcreature(SBYTE x, SBYTE y, UBYTE species, UBYTE exception)
  2445. {   UBYTE i;    
  2446.  
  2447.     for (i = 0; i <= CREATURES; i++)
  2448.         if
  2449.         (   creature[i].alive
  2450.          && creature[i].x == x
  2451.          && creature[i].y == y
  2452.          && creature[i].species == species
  2453.          && i != exception
  2454.         )
  2455.             return i;
  2456.     return 255; /* error code
  2457.  */
  2458. }
  2459. MODULE SBYTE whichteleport(SBYTE x, SBYTE y)
  2460. {   SBYTE which;
  2461.  
  2462.     for (which = 0; which <= 3; which++)
  2463.         if (teleport[level][which].alive && teleport[level][which].x == x && teleport[level][which].y == y)
  2464.             return((SBYTE) which);
  2465.     return((SBYTE) -1); /* error code
  2466.  */
  2467. }
  2468.  
  2469. MODULE void wormbullet(SBYTE player)
  2470. {   ABOOL   finished,
  2471.             flag            = FALSE,
  2472.             ok              = FALSE,
  2473.             lettered        = FALSE;
  2474.     LONG    score;
  2475.     SBYTE   distance,
  2476.             thissy,
  2477.             i, j,
  2478.             x, y;
  2479.  
  2480.     if (!worm[player].ammo)
  2481.     {       stat(player, BONUS);
  2482.         if (worm[player].speed == FAST)
  2483.             distance = FASTDISTANCE;
  2484.         elif (worm[player].speed == NORMAL)
  2485.             distance = NORMALDISTANCE;
  2486.         else
  2487.         {    /* assert(worm[player].speed == SLOW); */
  2488.             distance = SLOWDISTANCE;
  2489.         }
  2490.  
  2491.         /* check for metal */
  2492.  
  2493.         for (i = 1; i < distance; i++)
  2494.         {    x = xwrap(worm[player].x + (i * worm[player].deltax));
  2495.             y = ywrap(worm[player].y + (i * worm[player].deltay));
  2496.             if (field[x][y] == METAL)
  2497.                 flag = TRUE;
  2498.         }
  2499.  
  2500.         if (!flag)
  2501.         {    /* assert(abs(worm[player].deltax) == 1 && abs(worm[player].deltay) == 1); */
  2502.             x = xwrap(worm[player].x + worm[player].deltax * distance);
  2503.             y = ywrap(worm[player].y + worm[player].deltay * distance);
  2504.             thissy = field[x][y];
  2505.             if (thissy == TELEPORT)
  2506.             {   i = whichteleport(x, y);
  2507.                 if (!blocked(i, worm[player].deltax, worm[player].deltay))
  2508.                     ok = TRUE;
  2509.             }
  2510.             if (ok || ((thissy < STONE || thissy > GOAT) && thissy != METAL))
  2511.             {    effect(FXJUMP);
  2512.                 worm[player].deltax *= distance;
  2513.                 worm[player].deltay *= distance;
  2514.     }    }    }
  2515.     else
  2516.     {   effect(FXSHOOT);
  2517.         worm[player].ammo--;
  2518.         stat(player, AMMO);
  2519.         if (worm[player].bias)
  2520.             createmissile(player);
  2521.  
  2522.         if (worm[player].sideshot)
  2523.         {   bullet[7].alive      = bullet[8].alive      = TRUE;
  2524.             bullet[7].teleported = bullet[8].teleported = 0;
  2525.             bullet[7].visible    = bullet[8].visible    = TRUE;
  2526.             bullet[7].reflected  = bullet[8].reflected  = FALSE;
  2527.             bullet[7].x          = bullet[8].x          = worm[player].x;
  2528.             bullet[7].y          = bullet[8].y          = worm[player].y;
  2529.             if (!worm[player].deltax && worm[player].deltay)
  2530.             {   bullet[7].deltax = -1;
  2531.                 bullet[8].deltax = 1;
  2532.                 bullet[7].deltay = bullet[8].deltay = 0;
  2533.             } elif (worm[player].deltax && !worm[player].deltay)
  2534.             {   bullet[7].deltax = bullet[8].deltax = 0;
  2535.                 bullet[7].deltay = -1;
  2536.                 bullet[8].deltay = 1;
  2537.             } else /* worm is diagonal */
  2538.             {   if (worm[player].deltax == worm[player].deltay)
  2539.                 {   bullet[7].deltax = 1;
  2540.                     bullet[7].deltay = -1;
  2541.                 } else
  2542.                 {   bullet[7].deltax = -1;
  2543.                     bullet[7].deltay = -1;
  2544.                 }
  2545.                 bullet[8].deltax = -bullet[7].deltax;
  2546.                 bullet[8].deltay = -bullet[7].deltay;
  2547.         }   }
  2548.  
  2549.         for (i = 0; i <= worm[player].power; i++)
  2550.         {   bullet[i].alive      = TRUE;
  2551.             bullet[i].teleported = 0;
  2552.             bullet[i].visible    = TRUE;
  2553.             bullet[i].reflected  = FALSE;
  2554.             bullet[i].deltax     = worm[player].deltax;
  2555.             bullet[i].deltay     = worm[player].deltay;
  2556.             if (i % 2 == 0)
  2557.                 distance = i / 2;
  2558.             else distance = -((i + 1) / 2);
  2559.             if (worm[player].deltax == 0)
  2560.             {   bullet[i].x = worm[player].x + distance;
  2561.                 bullet[i].y = worm[player].y;
  2562.             } elif (worm[player].deltay == 0)
  2563.             {   bullet[i].x = worm[player].x;
  2564.                 bullet[i].y = worm[player].y + distance;
  2565.             } else
  2566.             {   switch (i)
  2567.                 {
  2568.                 case 0:
  2569.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2570.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2571.                 break;
  2572.                 case 1:
  2573.                     bullet[i].x = worm[player].x + worm[player].deltax;
  2574.                     bullet[i].y = worm[player].y;
  2575.                 break;
  2576.                 case 2:
  2577.                     bullet[i].x = worm[player].x;
  2578.                     bullet[i].y = worm[player].y + worm[player].deltay;
  2579.                 break;
  2580.                 case 3:
  2581.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2582.                     bullet[i].y = worm[player].y;
  2583.                 break;
  2584.                 case 4:
  2585.                     bullet[i].x = worm[player].x;
  2586.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2587.                 break;
  2588.                 case 5:
  2589.                     bullet[i].x = worm[player].x + worm[player].deltax * 2;
  2590.                     bullet[i].y = worm[player].y - worm[player].deltay;
  2591.                 break;
  2592.                 case 6:
  2593.                     bullet[i].x = worm[player].x - worm[player].deltax;
  2594.                     bullet[i].y = worm[player].y + worm[player].deltay * 2;
  2595.                 break;
  2596.                 default:
  2597.                 break;
  2598.         }   }   }
  2599.  
  2600.         /* Bullets are now set up. */
  2601.  
  2602.         score = 0;
  2603.         finished = FALSE;
  2604.         while (!finished)
  2605.         {   finished = TRUE;
  2606.             for (i = 0; i <= 8; i++)
  2607.             {   if (bullet[i].alive)
  2608.                 {   finished = FALSE;
  2609.                     if (bullet[i].reflected)
  2610.                     {   bullet[i].x -= bullet[i].deltax;
  2611.                         bullet[i].y -= bullet[i].deltay;
  2612.                     } else
  2613.                     {   bullet[i].x += bullet[i].deltax;
  2614.                         bullet[i].y += bullet[i].deltay;
  2615.                     }
  2616.                     x = bullet[i].x;
  2617.                     y = bullet[i].y;
  2618.                     thissy = field[x][y];
  2619.                     if (!(valid(x, y)))
  2620.                         bullet[i].alive = FALSE;
  2621.                     elif (x == worm[player].x && y == worm[player].y)
  2622.                     {   /* hit by own bullet */
  2623.                         bullet[i].alive = FALSE;
  2624.                         if (worm[player].mode != ARMOUR)
  2625.                         {   worm[player].cause = FIRSTFIRE + player;
  2626.                             worm[player].victor = -1;
  2627.                             worm[player].alive = FALSE;
  2628.                     }   }
  2629.                     elif (thissy >= FIRSTHEAD && thissy <= LASTHEAD)
  2630.                     {   if (worm[thissy - FIRSTHEAD].mode != ARMOUR)
  2631.                         {   worm[thissy - FIRSTHEAD].cause = FIRSTFIRE + player;
  2632.                             worm[thissy - FIRSTHEAD].victor = player;
  2633.                             worm[thissy - FIRSTHEAD].alive = FALSE;
  2634.                             if (player != thissy - FIRSTHEAD)
  2635.                                 score += KILLWORM + HITSHOT;
  2636.                         } else effect(FXUSEARMOUR);
  2637.                         bullet[i].alive = FALSE;
  2638.                     } elif (thissy >= FIRSTPROTECTOR && thissy <= LASTPROTECTOR)
  2639.                     {   if (player != thissy - FIRSTPROTECTOR)
  2640.                         {   effect(FXUSEPROTECTOR);
  2641.                             bullet[i].alive = FALSE;
  2642.                         } else bullet[i].visible = FALSE;
  2643.                     } elif (thissy >= FIRSTMISSILE && thissy <= LASTMISSILE)
  2644.                     {   if (player != thissy - FIRSTMISSILE)
  2645.                             creature[whichcreature(x, y, MISSILE, 255)].alive = FALSE;
  2646.                         else bullet[i].visible = FALSE;
  2647.                     } elif (thissy >= FIRSTDRIP && thissy <= LASTDRIP)
  2648.                     {   j = whichcreature(x, y, DRIP, 255);
  2649.                         creature[j].alive = FALSE;
  2650.                     } elif (thissy >= FIRSTLETTER && thissy <= LASTLETTER)
  2651.                     {   wormletter(player, thissy);
  2652.                         lettered = TRUE;
  2653.                     } else
  2654.                     {   switch(thissy)
  2655.                         {
  2656.                         case METAL:
  2657.                             if (bullet[i].reflected)
  2658.                                 bullet[i].alive = FALSE;
  2659.                             else
  2660.                             {   bullet[i].reflected = TRUE;
  2661.                                 bullet[i].x -= bullet[i].deltax * 2;
  2662.                                 bullet[i].y -= bullet[i].deltay * 2;
  2663.                             }
  2664.                             break;
  2665.                         case STONE:
  2666.                         case WHIRLWIND:
  2667.                             bullet[i].alive = FALSE;
  2668.                         break;
  2669.                         case ORB:
  2670.                             bullet[i].alive = FALSE;
  2671.                             j = whichcreature(x, y, ORB, 255);
  2672.                             if (creature[j].mode != ARMOUR)
  2673.                             {   creature[j].explode = TRUE;
  2674.                                 score += creature[j].score + HITSHOT;
  2675.                                 if (worm[player].bias)
  2676.                                     worm[player].lives += ORBBLOOD;
  2677.                             } else effect(FXUSEARMOUR);
  2678.                         break;
  2679.                         case TELEPORT:
  2680.                             j = whichteleport(bullet[i].x, bullet[i].y);
  2681.                             if (bullet[i].teleported == 2)
  2682.                                 bullet[i].alive = FALSE;
  2683.                             else
  2684.                             {   effect(FXUSETELEPORT);
  2685.                                 bullet[i].visible = FALSE;
  2686.                                 bullet[i].teleported++;
  2687.                                 bullet[i].x = teleport[level][partner(j)].x;
  2688.                                 bullet[i].y = teleport[level][partner(j)].y;
  2689.                                 score += TELPOINT;
  2690.                             }
  2691.                         break;
  2692.                         case WOOD:
  2693.                             if (!worm[player].bias)
  2694.                                 bullet[i].alive = FALSE;
  2695.                         break;
  2696.                         case GOAT:
  2697.                             creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  2698.                             change(x, y, BONUS);
  2699.                             score += KILLGOAT + HITSHOT;
  2700.                             if (worm[player].bias)
  2701.                                 worm[player].lives += GOATBLOOD;
  2702.                             bullet[i].alive = FALSE;
  2703.                         break;
  2704.                         case SKULL:
  2705.                             bullet[i].alive = FALSE;
  2706.                         break;
  2707.                         case FRAGMENT:
  2708.                             bullet[i].alive = FALSE;
  2709.                             creature[whichcreature(x, y, FRAGMENT, 255)].alive = FALSE;
  2710.                             change(x, y, EMPTY);
  2711.                         break;
  2712.                         case PENGUIN:
  2713.                             bullet[i].alive = FALSE;
  2714.                             creature[whichcreature(x, y, PENGUIN, 255)].alive = FALSE;
  2715.                             change(x, y, EMPTY);
  2716.                             score += KILLPENGUIN + HITSHOT;
  2717.                             if (worm[player].bias)
  2718.                                 worm[player].lives += PENGUINBLOOD;
  2719.                         break;
  2720.                         case DOG:
  2721.                             bullet[i].alive = FALSE;
  2722.                         break;
  2723.                         case CLOUD:
  2724.                             creature[whichcreature(x, y, CLOUD, 255)].alive = FALSE;
  2725.                         default:
  2726.                         break;
  2727.                     }   }
  2728.  
  2729.                     // x and y need this refreshing here
  2730.                     x = bullet[i].x;
  2731.                     y = bullet[i].y;
  2732.                     if (bullet[i].alive && bullet[i].visible)
  2733.                     {   draw(x, y, FIRSTFIRE + player);
  2734.                         if (worm[player].remnants)
  2735.                             field[x][y] = FIRSTFIRE + player;
  2736.                         elif (bullet[i].teleported)
  2737.                             change(x, y, GOLD);
  2738.                         else change(x, y, EMPTY);
  2739.         }   }   }   }
  2740.         if (lettered)
  2741.             putletter(player);
  2742.         wormscore(player, score);
  2743.         if (worm[player].bias)
  2744.             stat(player, LIFE);
  2745.         clearkybd();
  2746. }   }
  2747.  
  2748. MODULE void wormletter(SBYTE player, SBYTE thissy)
  2749. {    if (thissy == GREEN_C)
  2750.         effect(FX_C);
  2751.     elif (thissy == RED_O)
  2752.         effect(FX_O);
  2753.     elif (thissy == BLUE_M)
  2754.         effect(FX_M);
  2755.     elif (thissy == YELLOW_P)
  2756.         effect(FX_P);
  2757.     elif (thissy == GREEN_L)
  2758.         effect(FX_L);
  2759.     elif (thissy == BLUE_T)
  2760.         effect(FX_T);
  2761.     else
  2762.     {   /* assert(thissy == RED_E || thissy == YELLOW_E); */
  2763.         effect(FX_E);
  2764.     }
  2765.     letters[player][thissy - FIRSTLETTER] = TRUE;
  2766.     drawletter(player, thissy, NORMAL);
  2767.     wormscore(player, LETTERPOINT);
  2768. }
  2769.  
  2770. /* NAME     wormloop -- controls worms and protectors
  2771. SYNOPSIS    wormloop(SBYTE);
  2772. FUNCTION    Amiga-worm thinking, processing one keystroke from the
  2773.             worm's queue, all the worm's protectors' control, the
  2774.             worm's control.
  2775. MODULE      engine.c */
  2776.  
  2777. MODULE void wormloop(SBYTE player)
  2778. {   AUTO    ABOOL enclosed = FALSE, ok;
  2779.     AUTO    SBYTE animal = HEAD, bestgood, bestx, besty, c, d, dirx, diry,
  2780.                   good, i, iwhich, thisprot = 0, which, x, y, leftx,
  2781.                   rightx, topy, bottomy;
  2782.     AUTO    UBYTE counter;
  2783.     AUTO    ULONG score = 0;
  2784.     PERSIST SBYTE deltas[4][2][19] = // direction, x/y, counter
  2785. { { {    0,  0,  0,  0,  0, -1, -1, -1, -1, -1,  0,  0,  0,  0,  0,  1,  1,  1,  1}, // northwest
  2786.     {   -1, -1, -1, -1, -1,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0}
  2787.   },
  2788.   { {    0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0, -1, -1, -1, -1}, // northeast
  2789.     {   -1, -1, -1, -1, -1,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0}
  2790.   },
  2791.   { {    0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  0,  0,  0,  0,  0, -1, -1, -1, -1}, // southeast
  2792.     {    1,  1,  1,  1,  1,  0,  0,  0,  0,  0, -1, -1, -1, -1, -1,  0,  0,  0,  0}
  2793.   },
  2794.   { {    0,  0,  0,  0,  0, -1, -1, -1, -1, -1,  0,  0,  0,  0,  0,  1,  1,  1,  1}, // southwest
  2795.     {    1,  1,  1,  1,  1,  0,  0,  0,  0,  0, -1, -1, -1, -1, -1,  0,  0,  0,  0}
  2796. } };
  2797. PERSIST struct
  2798. {   SBYTE leftx, rightx, topy, bottomy;
  2799. } enclose[4] =
  2800. { { -5, -1, -5, -1 }, // northwest
  2801.   {  1,  5, -5, -1 }, // northeast
  2802.   {  1,  5,  1,  5 }, // southeast
  2803.   { -5, -1,  1,  5 }  // southwest
  2804. };
  2805.  
  2806.     /* AI: Amiga worm control
  2807.  
  2808.     Worm checks ahead, left and right one square. Assigns opinions to those
  2809.         three choices and then takes the appropriate one. */
  2810.  
  2811.     if (worm[player].control == AMIGA)
  2812.     {    if (!(rand() % 50))
  2813.             wormqueue(player, (rand() % 3) - 1, (rand() % 3) - 1);
  2814.         else
  2815.         {    bestgood = -128;
  2816.  
  2817.             for (i = 0; i <= 2; i++)
  2818.             {    switch(i) {
  2819.                 case 0:
  2820.                     dirx = worm[player].deltax;
  2821.                     diry = worm[player].deltay;
  2822.                     break;
  2823.                 case 1:
  2824.                     if (worm[player].deltax == 0)    /* if going north or south */
  2825.                     {    dirx = -1;                    /* then look west */
  2826.                         diry = 0;
  2827.                     } else                            /* if going east or west */
  2828.                     {    dirx = 0;                    /* then look north */
  2829.                         diry = -1;
  2830.                     }
  2831.                     break;
  2832.                 case 2:
  2833.                     if (worm[player].deltax == 0)    /* if going north or south */
  2834.                     {    dirx = 1;                    /* then look east */
  2835.                         diry = 0;
  2836.                     } else                            /* if going east or west */
  2837.                     {    dirx = 0;                    /* then look south */
  2838.                         diry = 1;
  2839.                     }
  2840.                     break;
  2841.                 default:
  2842.                     break;
  2843.                 }
  2844.                                 c = field[xwrap(worm[player].x + dirx)][ywrap(worm[player].y + diry)];
  2845.                                 if (c >= FIRSTLETTER && c <= LASTLETTER)
  2846.                     good = 100;
  2847.                                 elif (c <= LASTOBJECT)
  2848.                                         good = (SBYTE) object[c].score;
  2849.                                 elif (c == FIRSTPROTECTOR + player)
  2850.                     good = 6;
  2851.                                 elif (c == FIRSTFIRE + player)
  2852.                     good = 5;
  2853.                                 elif (c >= FIRSTTAIL && c <= LASTTAIL)
  2854.                                 {       if (player == c - FIRSTTAIL)
  2855.                         good = -30;
  2856.                     else good = -60;
  2857.                                 } else switch(c) {
  2858.                 case SKULL:
  2859.                     good = 70;
  2860.                 break;
  2861.                 case GOLD:
  2862.                     good = 50;
  2863.                 break;
  2864.                 case SILVER:
  2865.                     good = 40;
  2866.                 break;
  2867.                 case EMPTY:
  2868.                     good = 10;
  2869.                 break;
  2870.                 case WOOD:
  2871.                     good = -80;
  2872.                 break;
  2873.                 case STONE:
  2874.                     good = -90;
  2875.                 break;
  2876.                 case METAL:
  2877.                     good = -90;
  2878.                 break;
  2879.                 case GOAT:
  2880.                     good = -95;
  2881.                 break;
  2882.                 case WHIRLWIND:
  2883.                     good = -100;
  2884.                 break;
  2885.                 default:
  2886.                     good = -50; /* slime, heads, orbs, etc. */
  2887.                     break;
  2888.                 }
  2889.                 if (good > bestgood)
  2890.                 {    bestx = dirx;
  2891.                     besty = diry;
  2892.                     bestgood = good;
  2893.             }    }
  2894.  
  2895.             if (bestgood <= -60)
  2896.                 wormqueue(player, 0, 0);
  2897.             elif (bestgood < 0 && (!(rand() % 2)))
  2898.                 wormqueue(player, 0, 0);
  2899.             elif (bestx != worm[player].deltax || besty != worm[player].deltay)
  2900.                wormqueue(player, bestx, besty);
  2901.     }    }
  2902.  
  2903. /* remove a keystroke from the worm queue */
  2904.  
  2905. if (worm[player].pos != -1)
  2906. {   if (thewormqueue[player][0].deltax == 0 && thewormqueue[player][0].deltay == 0)
  2907.         wormbullet(player);
  2908.     else turnworm(player, thewormqueue[player][0].deltax, thewormqueue[player][0].deltay);
  2909.     if (--worm[player].pos != -1)
  2910.         for (i = 0; i <= worm[player].pos; i++)
  2911.         {   thewormqueue[player][i].deltax = thewormqueue[player][i + 1].deltax;
  2912.             thewormqueue[player][i].deltay = thewormqueue[player][i + 1].deltay;
  2913. }       }
  2914.  
  2915. /* move worm */
  2916.  
  2917. change(worm[player].x, worm[player].y, worm[player].last);
  2918. worm[player].x = xwrap(worm[player].x + worm[player].deltax);
  2919. worm[player].y = ywrap(worm[player].y + worm[player].deltay);
  2920. worm[player].last = FIRSTTAIL + player;
  2921.  
  2922. for (i = 0; i <= CREATURES; i++)
  2923. {   if (creature[i].alive && creature[i].species == DOG && creature[i].dormant > DORMANT && creature[i].type == player)
  2924.     {   dogqueue(i, worm[player].deltax, worm[player].deltay);
  2925.         if (creature[i].dormant < CHASING)
  2926.         {   creature[i].dormant++;
  2927.             draw(creature[i].x, creature[i].y, DOGAWAKENING);
  2928. }   }   }
  2929.  
  2930. /* The deltas are not changed back to the range of -1..1 until after the
  2931. dogs have looked at the queue. This enables them to jump. */
  2932.  
  2933. worm[player].deltax = bsign(worm[player].deltax);
  2934. worm[player].deltay = bsign(worm[player].deltay);
  2935.  
  2936. // check for enclosure
  2937.  
  2938. for (i = 0; i <= 3; i++)
  2939. {   x = worm[player].x;
  2940.     y = worm[player].y;
  2941.     ok = TRUE;
  2942.  
  2943.     for (counter = 0; counter <= 18; counter++)
  2944.     {   x = xwrap(x + deltas[i][0][counter]);
  2945.         y = ywrap(y + deltas[i][1][counter]);
  2946.         if (field[x][y] != FIRSTTAIL + player)
  2947.         {   ok = FALSE;
  2948.             break;
  2949.     }   }
  2950.  
  2951.     if (ok)
  2952.     {   effect(FXENCLOSURE);
  2953.         enclosed = TRUE;
  2954.           leftx = xwrap(worm[player].x + enclose[i].leftx);
  2955.          rightx = xwrap(worm[player].x + enclose[i].rightx);
  2956.            topy = ywrap(worm[player].y + enclose[i].topy);
  2957.         bottomy = ywrap(worm[player].y + enclose[i].bottomy);
  2958.         for (x = leftx; x <= rightx; x = xwrap(x + 1))
  2959.             for (y = topy; y <= bottomy; y = ywrap(y + 1))
  2960.             {   d = field[x][y];
  2961.                 if ((d >= FIRSTEMPTY && d <= LASTEMPTY) || (d >= FIRSTTAIL && d <= LASTTAIL && player != d - FIRSTTAIL))
  2962.                 {   change(x, y, FIRSTTAIL + player);
  2963.                     score += ENCLOSUREPOINT;
  2964. }   }       }   }
  2965.  
  2966. // move protectors
  2967.  
  2968. for (which = 0; which <= PROTECTORS; which++)
  2969. {   if (protector[player][which].alive)
  2970.     {   if (protector[player][which].visible)
  2971.             change(protector[player][which].x, protector[player][which].y, protector[player][which].last);
  2972.         else protector[player][which].visible = TRUE;
  2973.         protector[player][which].last = EMPTY;
  2974.         if (which == NOSE)
  2975.         {   protector[player][which].relx = worm[player].deltax * NOSEDISTANCE;
  2976.             protector[player][which].rely = worm[player].deltay * NOSEDISTANCE;
  2977.             if (!worm[player].affixer)
  2978.             {   worm[player].position = 0;
  2979.                 if (worm[player].deltax == 0)
  2980.                     protector[player][which].relx = worm[player].position;
  2981.                 elif (worm[player].deltay == 0)
  2982.                     protector[player][which].rely = worm[player].position;
  2983.                 elif (worm[player].position == -1)
  2984.                     protector[player][which].relx = worm[player].deltax * (NOSEDISTANCE - 1);
  2985.                 elif (worm[player].position == 1)
  2986.                     protector[player][which].rely = worm[player].deltay * (NOSEDISTANCE - 1);
  2987.         }   }
  2988.         elif (!worm[player].affixer)
  2989.         {   if (protector[player][which].relx == 1 && protector[player][which].rely == -1)
  2990.             {   protector[player][which].deltax = 0;
  2991.                 protector[player][which].deltay = 1;
  2992.             } elif (protector[player][which].relx == 1 && protector[player][which].rely == 1)
  2993.             {   protector[player][which].deltax = -1;
  2994.                 protector[player][which].deltay = 0;
  2995.             } elif (protector[player][which].relx == -1 && protector[player][which].rely == 1)
  2996.             {   protector[player][which].deltax = 0;
  2997.                 protector[player][which].deltay = -1;
  2998.             } elif (protector[player][which].relx == -1 && protector[player][which].rely == -1)
  2999.             {   protector[player][which].deltax = 1;
  3000.                 protector[player][which].deltay = 0;
  3001.             }
  3002.             protector[player][which].relx += protector[player][which].deltax;
  3003.             protector[player][which].rely += protector[player][which].deltay;
  3004.         }
  3005.         protector[player][which].x = worm[player].x + protector[player][which].relx;
  3006.         protector[player][which].y = worm[player].y + protector[player][which].rely;
  3007.         if (!valid(protector[player][which].x, protector[player][which].y))
  3008.             protector[player][which].visible = FALSE;
  3009. }   }
  3010.  
  3011. /* collision detection */
  3012.  
  3013. while (animal != NOSQUARE)
  3014. {   if (animal == HEAD)
  3015.     {   x = worm[player].x;
  3016.         y = worm[player].y;
  3017.         c = field[x][y];
  3018.         if (c >= FIRSTHEAD && c <= LASTHEAD)
  3019.             wormworm(x, y, player, c - FIRSTHEAD);
  3020.         elif (c >= FIRSTTAIL && c <= LASTTAIL)
  3021.         {   if (worm[player].mode == TONGUE)
  3022.             {    effect(FXUSETONGUE);
  3023.                 if (players > 1)
  3024.                     if (player == c - FIRSTTAIL)
  3025.                     {   score += TURNTOSILVER;
  3026.                         worm[player].last = SILVER;
  3027.                     } else
  3028.                     {   score += TURNTOGOLD;
  3029.                         worm[player].last = GOLD;
  3030.             }       }
  3031.             elif (!enclosed)
  3032.             {   worm[player].cause = c;
  3033.                 worm[player].alive = FALSE;
  3034.                 worm[player].victor = c - FIRSTTAIL;
  3035.         }   }
  3036.         elif (c == TIMEBOMB)
  3037.         {   /* push timebomb */
  3038.             which = whichcreature(x, y, TIMEBOMB, 255);
  3039.             if (valid(x + worm[player].deltax, y + worm[player].deltay))
  3040.             {   d = field[x + worm[player].deltax][y + worm[player].deltay];
  3041.                 if (d == TELEPORT)
  3042.                     score += BOMBOVEREDGE;
  3043.                 elif (d <= LASTEMPTY)
  3044.                 {   creature[which].x += worm[player].deltax;
  3045.                     creature[which].y += worm[player].deltay;
  3046.                     field[creature[which].x][creature[which].y] = TIMEBOMB;
  3047.                     draw(creature[which].x, creature[which].y, ZERO + creature[which].time);
  3048.                 } else
  3049.                 {   if (worm[player].mode == NULL)
  3050.                         draw(worm[player].x, worm[player].y, eachworm[player][0][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3051.                     else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3052.                     bombblast(HEAD, player, worm[player].x, worm[player].y);
  3053.                     creature[which].alive = FALSE;
  3054.             }   }
  3055.             else score += BOMBOVEREDGE;
  3056.         } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  3057.             protworm(x, y, c - FIRSTPROTECTOR, player);
  3058.         elif (c >= FIRSTMISSILE && c <= LASTMISSILE)
  3059.         {   i = whichcreature(x, y, MISSILE, 255);
  3060.             wormmissile(x, y, player, i);
  3061.         } elif (c >= FIRSTDRIP && c <= LASTDRIP)
  3062.         {   i = whichcreature(x, y, DRIP, 255);
  3063.             wormdrip(x, y, player, i);
  3064.         } elif (c == STONE || c == GOAT || c == METAL)
  3065.         {   worm[player].cause = c;
  3066.             worm[player].victor = -1;
  3067.             worm[player].alive = FALSE;
  3068.             ramming(player);
  3069.         } elif (c == WOOD)
  3070.         {   if (worm[player].mode != ARMOUR)
  3071.             {   worm[player].cause = WOOD;
  3072.                 worm[player].alive = FALSE;
  3073.                 worm[player].victor = -1;
  3074.         }   }
  3075.         elif (c == SLIME)
  3076.         {   if (worm[player].mode != ARMOUR)
  3077.             {   worm[player].cause = SLIME;
  3078.                 worm[player].alive = FALSE;
  3079.                 worm[player].victor = -1;
  3080.         }   }
  3081.         elif (c == PENGUIN)
  3082.     {   i = whichcreature(x, y, PENGUIN, 255);
  3083.             wormpenguin(x, y, player, i);
  3084.         } elif (c == WHIRLWIND)
  3085.         {   i = whichcreature(x, y, WHIRLWIND, 255);
  3086.             wormwhirlwind(x, y, player, i);
  3087.         } elif (c == DOG)
  3088.         {   i = whichcreature(x, y, DOG, 255);
  3089.             wormdog(x, y, player, i);
  3090.         } elif (c == ORB)
  3091.         {   i = whichcreature(x, y, ORB, 255);
  3092.             wormorb(x, y, player, i);
  3093.         } elif (c == FRAGMENT)
  3094.         {   i = whichcreature(x, y, FRAGMENT, 255);
  3095.             wormfrag(x, y, player, i);
  3096.         } elif (c == CLOUD)
  3097.         {   i = whichcreature(x, y, CLOUD, 255);
  3098.             cloudworm(x, y, i, player);
  3099.         } elif (c == TELEPORT)
  3100.         {   which = whichteleport(x, y);
  3101.             if (blocked(which, worm[player].deltax, worm[player].deltay))
  3102.             {   worm[player].cause = TELEPORT;
  3103.                 worm[player].victor = -1;
  3104.                 worm[player].alive = FALSE;
  3105.                 ramming(player);
  3106.             } else
  3107.             {   effect(FXUSETELEPORT);
  3108.                 score += TELPOINT;
  3109.                 worm[player].x = xwrap(teleport[level][partner(which)].x + worm[player].deltax);
  3110.                 worm[player].y = ywrap(teleport[level][partner(which)].y + worm[player].deltay);
  3111.         }   }
  3112.         elif (c >= FIRSTFIRE && c <= LASTFIRE)
  3113.         {   if (player != c - FIRSTFIRE && worm[player].mode != ARMOUR)
  3114.             {   worm[player].cause = REMNANTS;
  3115.                 worm[player].victor = c - FIRSTFIRE;
  3116.                 worm[player].alive = FALSE;
  3117.     }   }   }
  3118.     else
  3119.     {   /* assert(animal == PROTECTOR); */
  3120.         x = protector[player][thisprot].x;
  3121.         y = protector[player][thisprot].y;
  3122.         c = field[x][y];
  3123.         if (c >= FIRSTHEAD && c <= LASTHEAD)
  3124.             protworm(x, y, player, c - FIRSTHEAD);
  3125.         elif (c >= FIRSTTAIL && c <= LASTTAIL)
  3126.         {   if (player == c - FIRSTTAIL || worm[player].mode == TONGUE)
  3127.                 protector[player][thisprot].visible = FALSE;
  3128.         } elif (c >= FIRSTPROTECTOR && c <= LASTPROTECTOR)
  3129.             protprot(x, y, player, c - FIRSTPROTECTOR);
  3130.         elif (c == STONE || c == WOOD || c == METAL || c == TIMEBOMB || c == TELEPORT)
  3131.             protector[player][thisprot].visible = FALSE;
  3132.         elif (c >= FIRSTMISSILE && c <= LASTMISSILE)
  3133.         {   i = whichcreature(x, y, MISSILE, 255);
  3134.             protmissile(x, y, player, i);
  3135.         } elif (c == WHIRLWIND)
  3136.         {   i = whichcreature(x, y, WHIRLWIND, 255);
  3137.             protwhirlwind(x, y, player, i);
  3138.         } elif (c == DOG)
  3139.         {   i = whichcreature(x, y, DOG, 255);
  3140.             protdog(x, y, player, i);
  3141.         } elif (c >= FIRSTDRIP && c <= LASTDRIP)
  3142.         {   i = whichcreature(x, y, DRIP, 255);
  3143.             protdrip(x, y, player, i);
  3144.         } elif (c == PENGUIN)
  3145.         {   i = whichcreature(x, y, PENGUIN, 255);
  3146.             protpenguin(x, y, player, i);
  3147.         } elif (c == ORB)
  3148.         {   i = whichcreature(x, y, ORB, 255);
  3149.             protorb(x, y, player, i);
  3150.         } elif (c == FRAGMENT)
  3151.         {   i = whichcreature(x, y, FRAGMENT, 255);
  3152.             protfrag(x, y, player, i);
  3153.         } elif (c == CLOUD)
  3154.         {   i = whichcreature(x, y, CLOUD, 255);
  3155.             cloudprot(x, y, i, player);
  3156.         } elif (c == GOAT)
  3157.         {   effect(FXUSEPROTECTOR);
  3158.             effect(FXGOATDEATH);
  3159.             creature[whichcreature(x, y, GOAT, 255)].alive = FALSE;
  3160.             protector[player][thisprot].last = BONUS;
  3161.             score += KILLGOAT;
  3162.             if (worm[player].bias)
  3163.             {   worm[player].lives += GOATBLOOD;
  3164.                 stat(player, LIFE);
  3165.     }   }   }
  3166.  
  3167.     /* The next collisions apply equally to worms and protectors. */
  3168.  
  3169.     if (c >= FIRSTLETTER && c <= LASTLETTER)
  3170.     {   wormletter(player, c);
  3171.         putletter(player);
  3172.     } elif (c <= LASTOBJECT)
  3173.         score += wormobject(player, x, y);
  3174.     else
  3175.     {   switch(c)
  3176.         {
  3177.         case EMPTY:
  3178.             score += EMPTYPOINT;
  3179.         break;
  3180.         case SILVER:
  3181.             score += SILVERPOINT;
  3182.         break;
  3183.         case GOLD:
  3184.             score += GOLDPOINT;
  3185.         break;
  3186.         case SKULL:
  3187.             effect(FXGETSKULL);
  3188.             score += SKULLPOINT;
  3189.             for (which = 0; which <= 3; which++)
  3190.             {   if (worm[which].alive == FALSE && worm[which].x == worm[player].x && worm[which].y == worm[player].y)
  3191.                     iwhich = which;
  3192.             }
  3193.             worm[player].bias += worm[iwhich].bias;
  3194.             if (worm[player].bias > 0)
  3195.             {   stat(player, BIAS);
  3196.                 worm[iwhich].bias = 0;
  3197.                 stat(iwhich, BIAS);
  3198.             }
  3199.             worm[player].multi *= worm[iwhich].multi;
  3200.             if (worm[player].multi > 1)
  3201.             {   if (worm[player].multi > MULTILIMIT)
  3202.                     worm[player].multi = MULTILIMIT;
  3203.             }
  3204.             worm[player].power += worm[iwhich].power;
  3205.             if (worm[player].power > 1)
  3206.             {   if (worm[player].power > POWERLIMIT)
  3207.                     worm[player].power = POWERLIMIT;
  3208.                 stat(player, POWER);
  3209.                 worm[iwhich].power = 0;
  3210.                 stat(iwhich, POWER);
  3211.             }
  3212.             worm[player].ammo += worm[iwhich].ammo;
  3213.             if (worm[player].ammo > 0)
  3214.             {   stat(player, AMMO);
  3215.                 worm[iwhich].ammo = 0;
  3216.                 stat(iwhich, AMMO);
  3217.             }
  3218.             worm[player].armour += worm[iwhich].armour;
  3219.             if (worm[player].armour > 0)
  3220.             {   stat(player, ARMOUR);
  3221.                 worm[iwhich].armour = 0;
  3222.                 stat(iwhich, ARMOUR);
  3223.             }
  3224.             worm[player].tongue += worm[iwhich].tongue;
  3225.             if (worm[player].tongue > 0)
  3226.             {   stat(player, TONGUE);
  3227.                 worm[iwhich].tongue = 0;
  3228.                 stat(iwhich, TONGUE);
  3229.             }
  3230.             if (worm[player].armour > 0 || worm[player].tongue > 0)
  3231.             {   if (worm[player].armour >= worm[player].tongue)
  3232.                     worm[player].mode = ARMOUR;
  3233.                 else worm[player].mode = TONGUE;
  3234.             }
  3235.             if (worm[iwhich].nitro)
  3236.             {   worm[player].nitro = TRUE;
  3237.                 stat(player, NITRO);
  3238.                 worm[iwhich].nitro = FALSE;
  3239.                 worm[iwhich].speed = NORMAL;
  3240.                 stat(iwhich, NITRO);
  3241.             }
  3242.             if (worm[iwhich].affixer)
  3243.                 worm[player].affixer = TRUE;
  3244.             if (worm[iwhich].remnants)
  3245.                 worm[player].remnants = TRUE;
  3246.             if (worm[iwhich].sideshot)
  3247.                 worm[player].sideshot = TRUE;
  3248.             for (which = 0; which <= LETTERS; which++)
  3249.                 if (letters[iwhich][which])
  3250.                 {   drawletter(iwhich, FIRSTLETTER + which, BLACK);
  3251.                     if (!letters[player][which])
  3252.                     {   letters[player][which] = TRUE;
  3253.                         drawletter(player, FIRSTLETTER + which, NORMAL);
  3254.                 }   }
  3255.         break;
  3256.         default:
  3257.         break;
  3258.     }   } 
  3259.     if (animal == HEAD)
  3260.     /* it is important that HEAD is done before PROTECTORs */
  3261.     {   field[worm[player].x][worm[player].y] = FIRSTHEAD + player;
  3262.         if (worm[player].alive)
  3263.         {   switch (worm[player].mode)
  3264.             {
  3265.             case NULL:
  3266.                 draw(worm[player].x, worm[player].y, eachworm[player][0][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3267.             break;
  3268.             case TONGUE:
  3269.                 if (worm[player].tongue < 10 && (r / SLOW) % 2 == 0)
  3270.                     draw(worm[player].x, worm[player].y, WHITENED);
  3271.                 else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3272.             break;
  3273.             case ARMOUR:
  3274.                 if (worm[player].armour < 10 && (r / SLOW) % 2 == 0)
  3275.                     draw(worm[player].x, worm[player].y, WHITENED);
  3276.                 else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3277.             break;
  3278.             default:
  3279.             break;
  3280.         }   }
  3281.         else draw(worm[player].x, worm[player].y, SKULL);
  3282.         animal = PROTECTOR;
  3283.     } elif (animal == PROTECTOR)
  3284.     {   if (protector[player][thisprot].alive && protector[player][thisprot].visible)
  3285.             change(x, y, FIRSTPROTECTOR + player);
  3286.         do
  3287.         {   thisprot++;
  3288.         } while ((!protector[player][thisprot].alive || !valid(protector[player][thisprot].x, protector[player][thisprot].y)) && thisprot <= PROTECTORS);
  3289.     if (thisprot > PROTECTORS)
  3290.             animal = NOSQUARE;
  3291. }   }
  3292. wormscore(player, score);
  3293. }
  3294.  
  3295. void wormscore(SBYTE player, LONG score)
  3296. {   worm[player].score += score * worm[player].multi * players;
  3297.     stat(player, BONUS);
  3298. }
  3299.  
  3300. MODULE SWORD wsign(SWORD value)
  3301. {    if (value < 0)
  3302.         return (-1);
  3303.     elif (value > 0)
  3304.         return (1);
  3305.     else
  3306.         return (0);
  3307. }
  3308.  
  3309. AGLOBAL SBYTE xwrap(SBYTE x)
  3310. {    if (x < 0)
  3311.         x += FIELDX + 1;
  3312.     elif (x > FIELDX)
  3313.         x -= FIELDX + 1;
  3314.     return(x);
  3315. }
  3316. AGLOBAL SBYTE ywrap(SBYTE y)
  3317. {    if (y < 0)
  3318.         y += FIELDY + 1;
  3319.     elif (y > FIELDY)
  3320.         y -= FIELDY + 1;
  3321.     return(y);
  3322. }
  3323.  
  3324. MODULE void ramming(SBYTE player)
  3325. {   SBYTE i;
  3326.  
  3327.     worm[player].x = xwrap(worm[player].x - worm[player].deltax);
  3328.     worm[player].y = ywrap(worm[player].y - worm[player].deltay);
  3329.     for (i = 0; i <= PROTECTORS; i++)
  3330.     {   /* no point checking whether the protectors are alive or dead
  3331.  */
  3332.         protector[player][i].x -= worm[player].deltax;
  3333.         protector[player][i].y -= worm[player].deltay;
  3334. }   }
  3335.  
  3336. MODULE SWORD atleast(SWORD value, SWORD minimum)
  3337. {    if (value < minimum)
  3338.         return(minimum);
  3339.     else return(value);
  3340. }
  3341.  
  3342. MODULE void orbscore(SBYTE which, ULONG score)
  3343. {   creature[which].score += score * creature[which].multi;
  3344. }
  3345.  
  3346. MODULE void __inline change(SBYTE x, SBYTE y, UBYTE image)
  3347. {   field[x][y] = image;
  3348.     draw(x, y, image);
  3349. }
  3350.  
  3351. MODULE void createmissile(UBYTE player)
  3352. {   UBYTE i;
  3353.  
  3354.     for (i = 0; i <= CREATURES; i++)
  3355.         if (!creature[i].alive)
  3356.         {   effect(FXMISSILEACTIVE);
  3357.             creature[i].alive      = TRUE;
  3358.             creature[i].x          = worm[player].x;
  3359.             creature[i].y          = worm[player].y;
  3360.             creature[i].species    = MISSILE;
  3361.             creature[i].type       = player;
  3362.             creature[i].last       = EMPTY;
  3363.             creature[i].visible    = FALSE;
  3364.             if (level)
  3365.                 creature[i].speed  = (SBYTE) atleast(MISSILESPEED - (level / 2), 1);
  3366.             else creature[i].speed = BONUSMISSILESPEED;
  3367.             break;
  3368. }       }
  3369.  
  3370. /* WormWars FSET 5.6 format for fieldset contents and high
  3371. score table (Amiga and IBM-PC), as follows:
  3372.  
  3373. header
  3374.         TEXT[]                          "FSET 5.6" (NULL-terminated)
  3375.     SBYTE                levels;
  3376. high score table
  3377.     for (slot = 0; slot <= HISCORES; slot++)
  3378.     {    SBYTE            hiscore[slot].player,
  3379.                     hiscore[slot].level;
  3380.         SLONG            hiscore[slot].score;
  3381.         TEXT[]            hiscore[slot].name (NULL-terminated)
  3382.         TEXT[]            hiscore[slot].time (NULL-terminated)
  3383.         TEXT[]            hiscore[slot].date (NULL-terminated)
  3384.     }
  3385. level data
  3386.     for (level = 0; level <= levels; level++)
  3387.     {    SBYTE            startx[level],
  3388.                         starty[level];
  3389.         ABOOL            teleport[level][0].alive;
  3390.         SBYTE            teleport[level][0].x,
  3391.                         teleport[level][0].y;
  3392.         ABOOL            teleport[level][1].alive;
  3393.         SBYTE            teleport[level][1].x,
  3394.                         teleport[level][1].y;
  3395.         for (x = 0; x <= FIELDX; x++)
  3396.             for (y = 0; y <= FIELDY; y++)
  3397.                 SBYTE    board[level][x][y];
  3398.     }
  3399. version string
  3400.         TEXT[]                          "$VER: Worm Wars 5.61 (dd.mm.yy) $" (NULL-terminated) */
  3401.  
  3402. MODULE SBYTE onlyworm(ABOOL alive)
  3403. {   UBYTE i, theworm, worms = 0;
  3404.  
  3405.     for (i = 0; i <= 3; i++)
  3406.         if (worm[i].control != NONE && ((!alive) || worm[i].lives))
  3407.         {   theworm = i;
  3408.             worms++;
  3409.         }
  3410.     if (worms == 1)
  3411.         return (SBYTE) theworm;
  3412.     else return -1;
  3413. }
  3414.  
  3415. /* cloud, prot, worm, dog, drip, frag, missile, orb, penguin, whirlwind
  3416.  
  3417. Whichever is earlier in that list comes earlier in the function name. For
  3418. example, frag-orb and orb-frag collisions both use fragorb(): there is no
  3419. such routine as orbfrag(). Also, there are no such routines as dripdrip()
  3420. and penguinpenguin(). */
  3421.  
  3422. MODULE void dogdog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3423. {   creature[which1].alive = FALSE;
  3424.     creature[which2].alive = FALSE;
  3425.     change(x, y, LIFE);
  3426. }
  3427. MODULE void dogdrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3428. {   creature[which1].alive = FALSE;
  3429. }
  3430. MODULE void dogfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3431. {   creature[which1].alive = FALSE;
  3432.     creature[which2].alive = FALSE;
  3433.     change(x, y, BONUS);
  3434. }
  3435. MODULE void dogmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3436. {   creature[which1].alive = FALSE;
  3437.     creature[which2].alive = FALSE;
  3438.     change(x, y, BONUS);
  3439. }
  3440. MODULE void dogorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3441. {   creature[which1].alive = FALSE;
  3442. }
  3443. MODULE void dogpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3444. {   creature[which2].alive = FALSE;
  3445. }
  3446. MODULE void dogwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3447. {   creature[which1].alive = FALSE;
  3448. }
  3449. MODULE void dripfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3450. {   creature[which1].alive = FALSE;
  3451.     creature[which2].alive = FALSE;
  3452.     change(x, y, BONUS);
  3453. }
  3454. MODULE void dripmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3455. {   /* drip lives, missile dies
  3456.  */
  3457.     creature[which2].alive = FALSE;
  3458. }
  3459. MODULE void driporb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3460. {   creature[which1].alive = FALSE;
  3461.     if (creature[which2].mode != ARMOUR)
  3462.     {   creature[which2].explode = TRUE;
  3463.         draw(x, y, EMPTY);
  3464. }   }
  3465. MODULE void drippenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3466. {   creature[which2].alive = FALSE;
  3467. }
  3468. MODULE void dripwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3469. {   creature[which1].alive = FALSE;
  3470. }
  3471. MODULE void fragfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3472. {   effect(FXTHUD);
  3473.     creature[which1].alive = FALSE;
  3474.     creature[which2].alive = FALSE;
  3475.     draw(x, y, EMPTY);
  3476. }
  3477. MODULE void fragmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3478. {   creature[which1].alive = FALSE;
  3479.     creature[which2].alive = FALSE;
  3480.     change(x, y, EMPTY);
  3481. }
  3482. MODULE void fragorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3483. {   creature[which1].alive = FALSE;
  3484.     if (creature[which2].mode != ARMOUR)
  3485.     {   creature[which2].explode = TRUE;
  3486.         draw(x, y, EMPTY);
  3487.     } else effect(FXUSEARMOUR);
  3488. }
  3489. MODULE void fragpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3490. {   creature[which2].alive = FALSE;
  3491. }
  3492. MODULE void fragwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3493. {   creature[which1].alive = FALSE;
  3494. }
  3495. MODULE void missilemissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3496. {   creature[which1].alive = FALSE;
  3497.     creature[which2].alive = FALSE;
  3498.     change(x, y, BONUS);
  3499. }
  3500. MODULE void missilepenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3501. {   creature[which2].alive = FALSE;
  3502. }
  3503. MODULE void missilewhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3504. {   creature[which1].alive = FALSE;
  3505. }
  3506. MODULE void orborb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3507. {   effect(FXORBDEATH);
  3508.     creature[which1].alive = FALSE;
  3509.     creature[which2].alive = FALSE;
  3510.     change(x, y, BONUS);
  3511. }
  3512. MODULE void orbmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3513. {   if (creature[which1].mode != ARMOUR)
  3514.     {   effect(FXORBDEATH);
  3515.         creature[which1].alive = FALSE;
  3516.         creature[which2].alive = FALSE;
  3517.         change(x, y, BONUS);
  3518.         wormscore(creature[which2].type, creature[which1].score);
  3519.         if (worm[creature[which2].type].bias)
  3520.         {   worm[creature[which2].type].lives += ORBBLOOD;
  3521.             stat(creature[which2].type, LIFE);
  3522.     }   }
  3523.     else effect(FXUSEARMOUR);
  3524. }
  3525. MODULE void orbpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3526. {   creature[which2].alive = FALSE;
  3527.     if (creature[which1].mode == ARMOUR)
  3528.         orbscore(which1, KILLPENGUIN);
  3529.     else
  3530.     {   creature[which1].alive = FALSE;
  3531.         change(x, y, BONUS);
  3532. }   }
  3533. MODULE void orbwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3534. {   creature[which1].alive = FALSE;
  3535. }
  3536. MODULE void penguinwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3537. {   creature[which1].alive = FALSE;
  3538. }
  3539. MODULE void whirlwindwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3540. {   creature[which1].alive = FALSE;
  3541.     creature[which2].alive = FALSE;
  3542.     change(x, y, LIFE);
  3543. }
  3544. MODULE void wormdog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3545. {   if (creature[which2].dormant == DORMANT)
  3546.     {   effect(FXDOGAWAKENS);
  3547.         creature[which2].dormant = AWAKENING;
  3548.         creature[which2].type = which1;
  3549.         worm[which1].last = DOG;
  3550.     } else
  3551.     {   creature[which2].alive = FALSE;
  3552.         if (worm[which1].mode != ARMOUR)
  3553.         {   worm[which1].alive = FALSE;
  3554.             worm[which1].cause = DOG;
  3555.             worm[which1].victor = -1;
  3556. }   }   }
  3557. MODULE void wormdrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3558. {   creature[which2].alive = FALSE;
  3559.     if (which1 == creature[which2].type)
  3560.     {    effect(FXDRIP);
  3561.     wormscore(which1, DRIPBONUS);
  3562.     } else
  3563.     {    worm[which1].alive = FALSE;
  3564.         worm[which1].cause = FIRSTDRIP + creature[which2].type;
  3565.         worm[which1].victor = -1;
  3566. }   }
  3567. MODULE void wormfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3568. {   if (worm[which1].mode != ARMOUR)
  3569.     {    worm[which1].cause = FRAGMENT;
  3570.     worm[which1].victor = -1;
  3571.     worm[which1].alive = FALSE;
  3572.         creature[which2].alive = FALSE;
  3573.     } else
  3574.     {   effect(FXUSEARMOUR);
  3575.     reflect(which2);
  3576. }   }
  3577. MODULE void wormmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3578. {   if (creature[which2].type == which1)
  3579.         creature[which2].visible = FALSE;
  3580.     else
  3581.     {   creature[which2].alive = FALSE;
  3582.     if (worm[which1].mode != ARMOUR)
  3583.     {   worm[which1].cause = FIRSTMISSILE + creature[which2].type;
  3584.               worm[which1].victor = creature[which2].type;
  3585.               worm[which1].alive = FALSE;
  3586.         } else effect(FXUSEARMOUR);
  3587. }   }
  3588. MODULE void wormorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3589. {   if (worm[which1].mode == ARMOUR)
  3590.     {   effect(FXUSEARMOUR);
  3591.     effect(FXORBDEATH);
  3592.         wormscore(which1, creature[which2].score);
  3593.         creature[which2].alive = FALSE;
  3594.         if (worm[which1].bias)
  3595.         {   worm[which1].lives += ORBBLOOD;
  3596.             stat(which1, LIFE);
  3597.     }   }
  3598.     else
  3599.     {   if (creature[which2].mode == ARMOUR)
  3600.         {   effect(FXUSEARMOUR);
  3601.             orbscore(which2, KILLWORM);
  3602.         } else creature[which2].alive = FALSE;
  3603.     worm[which1].cause = ORB;
  3604.     worm[which1].victor = -1;
  3605.     worm[which1].alive = FALSE;
  3606. }   }
  3607. MODULE void wormpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3608. {   effect(FXPENGUINDEATH);
  3609.     creature[which2].alive = FALSE;
  3610.     if (worm[which1].armour)
  3611.     {   wormscore(which1, KILLPENGUIN);
  3612.     if (worm[which1].bias)
  3613.     {   worm[which1].lives += PENGUINBLOOD;
  3614.         stat(which1, LIFE);
  3615.     }   }
  3616.     else
  3617.     {   worm[which1].alive = FALSE;
  3618.         worm[which1].cause = PENGUIN;
  3619.         worm[which1].victor = -1;
  3620. }   }
  3621. MODULE void wormwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3622. {   worm[which1].cause = WHIRLWIND;
  3623.     worm[which1].victor = -1;
  3624.     worm[which1].alive = FALSE;
  3625. }
  3626. MODULE void wormworm(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3627. {   if (worm[which1].mode != TONGUE && worm[which2].mode != TONGUE)
  3628.     {   /* both worms die
  3629.  */
  3630.         worm[which1].cause  = FIRSTHEAD + which2;
  3631.         worm[which1].alive  = FALSE;
  3632.         worm[which1].victor = -1;
  3633.         worm[which2].cause  = FIRSTHEAD + which1;
  3634.         worm[which2].alive  = FALSE;
  3635.         worm[which2].victor = -1;
  3636.     } elif (worm[which1].mode == TONGUE && worm[which2].mode != TONGUE)
  3637.     {   /* 1st worm lives, 2nd worm dies
  3638.  */
  3639.         worm[which2].cause  = FIRSTHEAD + which1;
  3640.         worm[which2].alive  = FALSE;
  3641.         worm[which2].victor = which1;
  3642.     } elif (worm[which1].mode != TONGUE && worm[which2].mode == TONGUE)
  3643.     {   /* 1st worm dies, 2nd worm lives
  3644.  */
  3645.         worm[which1].cause  = FIRSTHEAD + which2;
  3646.         worm[which1].alive  = FALSE;
  3647.         worm[which1].victor = which2;
  3648. }   }
  3649. MODULE void protdog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3650. {   creature[which2].alive = FALSE;
  3651. }
  3652. MODULE void protdrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3653. {   creature[which2].alive = FALSE;
  3654.     if (which1 == creature[which2].type)
  3655.     {   effect(FXDRIP);
  3656.         wormscore(which1, DRIPBONUS);
  3657.     } else effect(FXUSEPROTECTOR);
  3658. }
  3659. MODULE void protfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3660. {   effect(FXUSEPROTECTOR);
  3661.     reflect(which2);
  3662. }
  3663. MODULE void protmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3664. {   if (which1 != creature[which2].type)
  3665.     {   effect(FXUSEPROTECTOR);
  3666.         creature[which2].alive = FALSE;
  3667.     } else creature[which2].visible = FALSE;
  3668. }
  3669. MODULE void protorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3670. {   effect(FXUSEPROTECTOR);
  3671.     effect(FXORBDEATH);
  3672.     wormscore(which1, creature[which2].score);
  3673.     creature[which2].alive = FALSE;
  3674.     if (worm[which1].bias)
  3675.     {   worm[which1].lives += ORBBLOOD;
  3676.         stat(which1, LIFE);
  3677. }   }
  3678. MODULE void protpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3679. {   effect(FXUSEPROTECTOR);
  3680.     effect(FXPENGUINDEATH);
  3681.     wormscore(which1, KILLPENGUIN);
  3682.     creature[which2].alive = FALSE;
  3683.     if (worm[which1].bias)
  3684.     {   worm[which1].lives += PENGUINBLOOD;
  3685.         stat(which1, LIFE);
  3686. }   }
  3687. MODULE void protwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3688. {   UBYTE i;
  3689.  
  3690.     for (i = 0; i <= PROTECTORS; i++)
  3691.          if (protector[which1][i].alive && protector[which1][i].x == x && protector[which1][i].y == y)
  3692.               protector[which1][i].alive = FALSE;    
  3693. }
  3694. MODULE void protworm(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3695. {   UBYTE i, j;
  3696.  
  3697.     for (i = 0; i <= PROTECTORS; i++)
  3698.          if (protector[which1][i].alive && protector[which1][i].x == x && protector[which1][i].y == y)
  3699.          {    j = i;
  3700.               break;
  3701.          }
  3702.  
  3703.     if (which1 != which2)
  3704.     {   if (worm[which2].mode != ARMOUR)
  3705.         {   effect(FXUSEPROTECTOR);
  3706.             worm[which2].cause  = FIRSTPROTECTOR + which1;
  3707.             worm[which2].victor = which1;
  3708.             worm[which2].alive  = FALSE;
  3709.         } else
  3710.         {   effect(FXUSEARMOUR);
  3711.             protector[which1][j].visible = FALSE;
  3712.     }   }
  3713.     else
  3714.     {   /* protector is over worm's own head; caused by ramming */
  3715.         protector[which1][j].visible = FALSE;
  3716. }   }
  3717. MODULE void protprot(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3718. {   UBYTE i, p1, p2;
  3719.  
  3720.     /* Find both protectors */
  3721.  
  3722.     for (i = 0; i <= PROTECTORS; i++)
  3723.     {   if (protector[which1][i].alive && protector[which1][i].x == x && protector[which1][i].y == y)
  3724.             p1 = i;
  3725.         if (protector[which2][i].alive && protector[which2][i].x == x && protector[which2][i].y == y)
  3726.             p2 = i;
  3727.     }
  3728.     protector[which1][p1].alive = FALSE;
  3729.     protector[which2][p2].alive = FALSE;
  3730.     change(x, y, EMPTY);
  3731. }
  3732. MODULE void cloudcloud(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3733. {   creature[which1].alive = FALSE;
  3734.     creature[which2].alive = FALSE;
  3735.     change(x, y, LIGHTNING);
  3736. }
  3737. MODULE void clouddog(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3738. {   creature[which2].alive = FALSE;
  3739. }
  3740. MODULE void clouddrip(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3741. {   creature[which2].alive = FALSE;
  3742. }
  3743. MODULE void cloudfrag(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3744. {   creature[which1].alive = FALSE;
  3745. }
  3746. MODULE void cloudmissile(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3747. {   creature[which2].alive = FALSE;
  3748. }
  3749. MODULE void cloudorb(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3750. {   creature[which1].alive = FALSE;
  3751. }
  3752. MODULE void cloudpenguin(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3753. {   creature[which2].alive = FALSE;
  3754. }
  3755. MODULE void cloudprot(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3756. {   creature[which1].alive = FALSE;
  3757. }
  3758. MODULE void cloudwhirlwind(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3759. {   creature[which1].alive = FALSE;
  3760. }
  3761. MODULE void cloudworm(SBYTE x, SBYTE y, UBYTE which1, UBYTE which2)
  3762. {   creature[which1].alive = FALSE;
  3763.     if (worm[which2].mode != ARMOUR)
  3764.     {   worm[which2].alive = FALSE;
  3765.         worm[which2].cause = CLOUD;
  3766.         worm[which2].victor = -1;
  3767. }   }
  3768.  
  3769. MODULE void magnetloop(void)
  3770. {   SBYTE i;
  3771.     UBYTE c;
  3772.  
  3773.     for (i = 0; i <= MAGNETS; i++)
  3774.         if (magnet[i].alive)
  3775.         {   // quick check to make sure this magnet is still valid
  3776.             if (field[magnet[i].x][magnet[i].y] != magnet[i].object)
  3777.                 magnet[i].alive = FALSE;
  3778.             else
  3779.             {   change(magnet[i].x, magnet[i].y, EMPTY);
  3780.                 magnet[i].x += bsign(worm[magnet[i].player].x - magnet[i].x);
  3781.                 magnet[i].y += bsign(worm[magnet[i].player].y - magnet[i].y);
  3782.                 c = field[magnet[i].x][magnet[i].y];
  3783.            
  3784.                 if ((c >= FIRSTEMPTY && c <= LASTEMPTY)
  3785.                  || (c >= FIRSTTAIL  && c <= LASTTAIL)
  3786.                  || (c >= FIRSTHEAD  && c <= LASTHEAD))
  3787.                 {   change(magnet[i].x, magnet[i].y, magnet[i].object);
  3788.                     if (c >= FIRSTHEAD && c <= LASTHEAD)
  3789.                     {   wormscore(c - FIRSTHEAD, wormobject(c - FIRSTHEAD, magnet[i].x, magnet[i].y));
  3790.                         change(magnet[i].x, magnet[i].y, FIRSTHEAD + magnet[i].player); // not entirely the right head image
  3791.                 }   }
  3792.                 else magnet[i].alive = FALSE;
  3793. }       }   }
  3794.  
  3795. MODULE ULONG wormobject(UBYTE player, SBYTE x, SBYTE y)
  3796. {   AUTO    UBYTE c = field[x][y], d;
  3797.     AUTO    ULONG score = object[c].score;
  3798.     AUTO    UBYTE i, j;
  3799.     AUTO    SBYTE xx, xxx, yy, yyy;
  3800.     AUTO    ABOOL done;
  3801.     PERSIST SBYTE otherfield[FIELDX + 1][FIELDY + 1];
  3802.  
  3803.     for (i = 0; i <= MAGNETS; i++)
  3804.         if (magnet[i].alive && x == magnet[i].x && y == magnet[i].y)
  3805.              magnet[i].alive = FALSE;
  3806.  
  3807.         if (c != SLAYER && c != BOMB && c != MISSILE && c != NITRO && c != POWER && c != AMMO)
  3808.             effect(FXGETOBJECT);
  3809.         switch(c)
  3810.         {
  3811.         case BONUS:
  3812.             i = rand() % (LETTERS + 1);
  3813.             letters[player][i] = TRUE;
  3814.             drawletter(player, FIRSTLETTER + i, NORMAL);
  3815.         break;
  3816.         case AMMO:
  3817.             effect(FXGETAMMO);
  3818.             worm[player].ammo += (rand() % 5) + 2; /* 2-6 bullets */
  3819.             stat(player, AMMO);
  3820.         break;
  3821.         case ARMOUR:
  3822.             worm[player].armour += MODEADD + (rand() % MODERAND);
  3823.             worm[player].mode = ARMOUR;
  3824.             stat(player, ARMOUR);
  3825.         break;
  3826.         case TONGUE:
  3827.             worm[player].tongue += MODEADD + (rand() % MODERAND);
  3828.             worm[player].mode = TONGUE;
  3829.             stat(player, TONGUE);
  3830.             worm[player].last = FIRSTTAIL + player;
  3831.         break;
  3832.         case NITRO:
  3833.             effect(FXGETNITRO);
  3834.             worm[player].nitro = TRUE;
  3835.             stat(player, NITRO);
  3836.         break;
  3837.         case BOMB:
  3838.             if (worm[player].mode == NULL)
  3839.                 draw(worm[player].x, worm[player].y, eachworm[player][0][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3840.             else draw(worm[player].x, worm[player].y, eachworm[player][1][worm[player].deltax + 1 + (worm[player].deltay + 1) * 3]);
  3841.                 bombblast(HEAD, player, worm[player].x, worm[player].y);
  3842.         break;
  3843.         case POWER:
  3844.             effect(FXGETPOWERUP);
  3845.             if (worm[player].power < POWERLIMIT)
  3846.             {   worm[player].power += 2;
  3847.                 stat(player, POWER);
  3848.             }
  3849.         break;
  3850.         case SLAYER:
  3851.             for (i = 0; i <= CREATURES; i++)
  3852.                 if (creature[i].alive)
  3853.                 {   if (creature[i].species == ORB)
  3854.                     {   effect(FXORBDEATH);
  3855.                         score += creature[i].score;
  3856.                         creature[i].explode = TRUE;
  3857.                         if (worm[player].bias)
  3858.                             worm[player].lives += ORBBLOOD;
  3859.                     } elif (creature[i].species == GOAT)
  3860.                     {   effect(FXGOATDEATH);
  3861.                         creature[i].alive = FALSE;
  3862.                         score += KILLGOAT;
  3863.                         if (worm[player].bias)
  3864.                             worm[player].lives += GOATBLOOD;
  3865.                         change(creature[i].x, creature[i].y, BONUS);
  3866.                     } elif (creature[i].species == DRIP)
  3867.                     {   creature[i].alive = FALSE;
  3868.                         change(creature[i].x, creature[i].y, EMPTY);
  3869.                     } elif (creature[i].species == MISSILE && creature[i].type != player)
  3870.                     {   creature[i].alive = FALSE;
  3871.                         change(creature[i].x, creature[i].y, EMPTY);
  3872.                 }   }
  3873.             for (i = 0; i <= 3; i++)
  3874.                 if (player != i && worm[i].mode != ARMOUR)
  3875.                 {   worm[i].alive = FALSE;
  3876.                     worm[i].cause = SLAYER;
  3877.                     worm[i].victor = player;
  3878.                 }
  3879.             for (x = 0; x <= FIELDX; x++)
  3880.                 for (y = 0; y <= FIELDY; y++)
  3881.                     if (field[x][y] == SLIME)
  3882.                         change(x, y, EMPTY);
  3883.             if (worm[player].bias)
  3884.                 stat(player, LIFE);
  3885.         break;
  3886.         case PROTECTOR:
  3887.             done = FALSE;
  3888.             for (i = 0; i <= PROTECTORS; i++)
  3889.                 if (!protector[player][i].alive && !done)
  3890.                 {   do
  3891.                     {   protector[player][i].relx = ((rand() % 2) * 2) - 1;
  3892.                         protector[player][i].rely = ((rand() % 2) * 2) - 1;
  3893.                         for (j = 0; j <= PROTECTORS; j++)
  3894.                             if (i == NOSE || !protector[player][j].alive || protector[player][j].x != xwrap(worm[player].x + protector[player][i].relx) || protector[player][j].y != ywrap(worm[player].y + protector[player][i].rely))
  3895.                             {   effect(FXPROTECTORBORN);
  3896.                                 done = TRUE;
  3897.                                 protector[player][i].alive = TRUE;
  3898.                                 protector[player][i].visible = FALSE;
  3899.                                 protector[player][i].last = EMPTY;
  3900.                                 if (i == NOSE)
  3901.                                     worm[player].position = -1;
  3902.                             }
  3903.                     } while (!done);
  3904.                 }
  3905.         break;
  3906.         case MISSILE:
  3907.             createmissile(player);
  3908.         break;
  3909.         case LIFE:
  3910.             worm[player].lives += (rand() % 5) + 2; /* 2-6 lives */
  3911.             stat(player, LIFE);
  3912.         break;
  3913.         case MULTIPLIER:
  3914.             if (worm[player].multi < MULTILIMIT)
  3915.                 worm[player].multi *= 2;
  3916.         break;
  3917.         case BIAS:
  3918.             worm[player].bias += MODEADD + (rand() % MODERAND);
  3919.             stat(player, BIAS);
  3920.         break;
  3921.         case ICE:
  3922.             worm[player].ice += ICEADD + (rand() % ICERAND);
  3923.             ice = player;
  3924.         break;
  3925.         case GROWER:
  3926.             effect(FXGETGROWER);
  3927.             /* grow silver */
  3928.             for (x = 0; x <= FIELDX; x++)
  3929.                 for (y = 0; y <= FIELDY; y++)
  3930.                     if (field[x][y] == SILVER)
  3931.                         for (xx = x - 1; xx <= x + 1; xx++)
  3932.                             for (yy = y - 1; yy <= y + 1; yy++)
  3933.                                 if (valid(xx, yy))
  3934.                                     if (field[xx][yy] == EMPTY || field[xx][yy] == TEMPTAIL)
  3935.                                         field[xx][yy] = TEMPSILVER;
  3936.             /* grow gold */
  3937.             for (x = 0; x <= FIELDX; x++)
  3938.                 for (y = 0; y <= FIELDY; y++)
  3939.                     if (field[x][y] == GOLD)
  3940.                         for (xx = x - 1; xx <= x + 1; xx++)
  3941.                             for (yy = y - 1; yy <= y + 1; yy++)
  3942.                                 if (valid(xx, yy))
  3943.                                     if (field[xx][yy] == EMPTY || field[xx][yy] == TEMPTAIL || field[xx][yy] == TEMPSILVER)
  3944.                                         field[xx][yy] = TEMPGOLD;
  3945.             /* update field */
  3946.             for (x = 0; x <= FIELDX; x++)
  3947.                 for (y = 0; y <= FIELDY; y++)
  3948.                     switch (field[x][y])
  3949.                     {
  3950.                     case TEMPGOLD:
  3951.                         change(x, y, GOLD);
  3952.                     break;
  3953.                     case TEMPSILVER:
  3954.                         change(x, y, SILVER);
  3955.                     break;
  3956.                     case TEMPTAIL:
  3957.                         change(x, y, FIRSTTAIL + player);
  3958.                     break;
  3959.                     default:
  3960.                     break;
  3961.                     }
  3962.         break;
  3963.         case TREASURE:
  3964.             treasurer = player;
  3965.             if (level)
  3966.             {   secondsperlevel = 0;
  3967.                 leveltype = rand() % 3;
  3968.                 if (leveltype == 0)
  3969.                 {   say("Bonus Level: Treasury!", worm[treasurer].colour);
  3970.                     leveltype = TREASURE;
  3971.                 } elif (leveltype == 1)
  3972.                 {   say("Bonus Level: Drips!", worm[treasurer].colour);
  3973.                     leveltype = DRIP;
  3974.                 } else
  3975.                 {   /* assert(leveltype == 2); */
  3976.                     say("Bonus Level: Clouds!", worm[treasurer].colour);
  3977.                     leveltype = CLOUD;
  3978.             }   }
  3979.             secondsperlevel += TREASUREADD + (rand() % TREASURERAND);
  3980.             if (level && leveltype != TREASURE)
  3981.                 secondsperlevel *= 2;
  3982.             if (level)
  3983.             {   stat(player, BONUS);
  3984.                 reallevel = level;
  3985.                 level = 0;
  3986.                 newlevel(player);
  3987.             }
  3988.         break;
  3989.         case AFFIXER:
  3990.             worm[player].affixer = TRUE;
  3991.         break;
  3992.         case SWITCHER:
  3993.             if (players >= 2)
  3994.                 for (x = 0; x <= FIELDX; x++)
  3995.                     for (y = 0; y <= FIELDY; y++)
  3996.                         if (field[x][y] >= FIRSTTAIL && field[x][y] <= LASTTAIL && field[x][y] != FIRSTTAIL + player)
  3997.                             change(x, y, FIRSTTAIL + player);
  3998.                         elif (worm[player].bias && field[x][y] >= FIRSTFIRE && field[x][y] <= LASTFIRE && field[x][y] != FIRSTFIRE + player)
  3999.                             change(x, y, FIRSTFIRE + player);
  4000.         break;
  4001.         case HEALER:
  4002.             if (worm[player].lives < 100)
  4003.                 worm[player].lives = 100;
  4004.             else worm[player].lives = LIVESLIMIT;
  4005.             stat(player, LIFE);
  4006.         break;
  4007.         case UMBRELLA:
  4008.             level += (rand() % 2) + 1;
  4009.             if (level >= levels)
  4010.                 level = level - 1;
  4011.             for (i = 0; i <= LETTERS; i++)
  4012.                 letters[player][i] = TRUE;
  4013.         break;
  4014.         case CLOCK:
  4015.             if (secondsleft)
  4016.                 secondsperlevel += (rand() % CLOCKRAND) + CLOCKADD;
  4017.         break;
  4018.         case SLOWER:
  4019.             for (i = 0; i <= CREATURES; i++)
  4020.                 if (creature[i].alive && creature[i].species != MISSILE)
  4021.                     creature[i].speed = (SBYTE) atleast(creature[i].speed * 2, VERYFAST);
  4022.         break;
  4023.         case PULSE:
  4024.             explosion(xwrap(worm[player].x - worm[player].deltax),
  4025.                       ywrap(worm[player].y - worm[player].deltay),
  4026.                                              worm[player].deltax,
  4027.                                              worm[player].deltay
  4028.                      );
  4029.         break;
  4030.     case REMNANTS:
  4031.         worm[player].remnants = TRUE;
  4032.     break;
  4033.     case SIDESHOT:
  4034.         worm[player].sideshot = TRUE;
  4035.     break;
  4036.     case MAGNET:
  4037.         i = 0;
  4038.         field[x][y] = EMPTY; // so that the magnet itself is destroyed
  4039.         for (xx = 0; xx <= FIELDX; xx++)
  4040.             for (yy = 0; yy <= FIELDY; yy++)
  4041.                 if (field[xx][yy] <= LASTOBJECT)
  4042.                 {   while (magnet[i].alive && i < MAGNETS)
  4043.                        i++;
  4044.                     if (i > MAGNETS)
  4045.                     {   break;
  4046.                     } else
  4047.                     {   magnet[i].x      = xx;
  4048.                         magnet[i].y      = yy;
  4049.                         magnet[i].object = field[xx][yy];
  4050.                         magnet[i].player = player;
  4051.                         magnet[i].alive  = TRUE;
  4052.                         i++;
  4053.                 }   }
  4054.     break;
  4055.     case CYCLONE:
  4056.         /* create cyclones */
  4057.         for (i = 0; i <= CREATURES; i++)
  4058.             if (!(creature[i].alive))
  4059.             {   effect(FXCYCLONE);
  4060.                 done = FALSE;
  4061.                 while (!done)
  4062.                 {   creature[i].x = rand() % (FIELDX + 1);
  4063.                     creature[i].y = (rand() % (FIELDY - 2)) + 3;
  4064.                     d = field[creature[i].x][creature[i].y];
  4065.                     if ((d >= FIRSTEMPTY && d <= LASTEMPTY) || (d >= FIRSTTAIL && d <= LASTTAIL))
  4066.                         done = TRUE;
  4067.                     /* Theoretically, this loop could hang... */
  4068.                 }
  4069.                 creature[i].last = EMPTY;
  4070.                 creature[i].speed = VERYFAST;
  4071.                 creature[i].visible = TRUE;
  4072.                 creature[i].deltax = 0;
  4073.                 creature[i].deltay = 0;
  4074.                 creature[i].species = WHIRLWIND;
  4075.                 creature[i].alive = TRUE;
  4076.                 change(creature[i].x, creature[i].y, WHIRLWIND);
  4077.                 break;
  4078.             }
  4079.     break;
  4080.     case LIGHTNING:
  4081.         for (xx = 0; xx <= FIELDX; xx++)
  4082.             for (yy = 0; yy <= FIELDY; yy++)
  4083.                 otherfield[xx][yy] = EMPTY;
  4084.         for (xx = 0; xx <= FIELDX; xx++)
  4085.             for (yy = 0; yy <= FIELDY; yy++)
  4086.                 if (field[xx][yy] == FIRSTTAIL + player)
  4087.                     for (xxx = xx - 1; xxx <= xx + 1; xxx++)
  4088.                         for (yyy = yy - 1; yyy <= yy + 1; yyy++)
  4089.                             if (valid(xxx, yyy))
  4090.                             {   d = field[xxx][yyy];
  4091.                                 if (d == ORB
  4092.                                  || d == GOAT
  4093.                                  || d == MISSILE
  4094.                                  || d == PENGUIN
  4095.                                  || d == FRAGMENT
  4096.                                  || (d >= FIRSTTAIL && d <= LASTTAIL && d != FIRSTTAIL + player)
  4097.                                  || (d >= FIRSTHEAD && d <= LASTHEAD)
  4098.                                  || (d >= FIRSTDRIP && d <= LASTDRIP)
  4099.                                  || d <= LASTOBJECT)
  4100.                                 {   otherfield[xxx][yyy] = TEMPLIGHTNING;
  4101.                                     draw(xxx, yyy, LIGHTNING);
  4102.                             }   }
  4103.         for (xx = 0; xx <= FIELDX; xx++)
  4104.         {   for (yy = 0; yy <= FIELDY; yy++)
  4105.             {   if (otherfield[xx][yy] == TEMPLIGHTNING)
  4106.                 {   d = field[xx][yy];
  4107.                     switch(d)
  4108.                     {
  4109.                     case ORB:
  4110.                         i = whichcreature(xx, yy, ORB, 255);
  4111.                         if (creature[i].mode == ARMOUR)
  4112.                             draw(xx, yy, ORBARMOUR);
  4113.                         else
  4114.                         {   creature[i].alive = FALSE;
  4115.                             score += creature[i].score;
  4116.                             change(xx, yy, BONUS);
  4117.                         }
  4118.                     break;
  4119.                     case GOAT:
  4120.                         creature[whichcreature(xx, yy, GOAT, 255)].alive = FALSE;
  4121.                         score += KILLGOAT;
  4122.                         change(xx, yy, BONUS);
  4123.                     break;
  4124.                     case MISSILE:
  4125.                         i = whichcreature(xx, yy, MISSILE, 255);
  4126.                         if (player != creature[i].type)
  4127.                         {   creature[i].alive = FALSE;
  4128.                             change(xx, yy, EMPTY);
  4129.                         } else draw(xx, yy, FIRSTMISSILE + player);
  4130.                     break;
  4131.                     case PENGUIN:
  4132.                         score += KILLPENGUIN;
  4133.                     // note no break here
  4134.                     case FRAGMENT:
  4135.                         creature[whichcreature(xx, yy, d, 255)].alive = FALSE;
  4136.                         change(xx, yy, EMPTY);
  4137.                     break;
  4138.                     default:
  4139.                         if (d >= FIRSTDRIP && d <= LASTDRIP)
  4140.                         {   creature[whichcreature(xx, yy, DRIP, 255)].alive = FALSE;
  4141.                             score += DRIPBONUS;
  4142.                         } elif (d >= FIRSTHEAD && d <= LASTHEAD)
  4143.                         {   if (player != d - FIRSTHEAD && worm[d - FIRSTHEAD].mode != ARMOUR)
  4144.                             {   worm[d - FIRSTHEAD].alive = FALSE;
  4145.                                 worm[d - FIRSTHEAD].cause = LIGHTNING;
  4146.                                 worm[d - FIRSTHEAD].victor = player;
  4147.                                 change(xx, yy, EMPTY);
  4148.                         }   }
  4149.                         else /* eg. tail */
  4150.                             change(xx, yy, EMPTY);
  4151.                     break;
  4152.         }   }   }   }
  4153.     break;
  4154.     default:
  4155.         /* assert(0); */
  4156.     break;
  4157.     }
  4158.     return(score);
  4159. }
  4160.  
  4161. /* Must have blank line at EOF. */
  4162.